home *** CD-ROM | disk | FTP | other *** search
/ Amiga Collections: Purity / Purity #21 (1994-01-12)(Diesel)(DE)[WB].zip / Purity #21 (1994-01-12)(Diesel)(DE)[WB].adf / PCQ-Dokus / PCQ_1.2b.Anl < prev    next >
Text File  |  1993-12-13  |  129KB  |  2,964 lines

  1.  
  2.  
  3.  
  4.       DEUTSCHE ANLEITUNG ZUM PCQ-PASCAL-COMPILER V1.2b VON PATRICK QUAID
  5.       ==================================================================
  6.  
  7.  
  8. Diese deutsche Anleitung wurde von Stefan Grad (GPD), Bahnhofstr. 37, 78588
  9. Denkingen, Deutschland verfaßt. Dabei wurde die deutsche Anleitung zur V1.1
  10. von der Purity #3 verwendet (verfaßt von einem gewissen "Olli"). Dieser be-
  11. ruft sich wiederum auf die Anleitung zur V1.0 von "Vinorkis ^O^".
  12. Die Anleitung ist jetzt fast vollständig (so etwa 90% der engl. Anleitung
  13. wurde übersetzt und noch ein paar Sachen hinzugefügt; diese Hinzufügungen
  14. könnt Ihr am Zusatz Anm.d.Ü. (Anmerkung des Übersetzers) erkennen).
  15. Das © Copyright der Anleitung liegt bei Patrick Quaid und mir (1993). Sie
  16. darf nur gemeinsam mit dem Compiler weitergegeben werden (ausgenommen davon
  17. ist die Purity: hier liegt PCQ 1.2b auf Disk 6 vor), wobei dann alle Copy-
  18. rightbestimmungen vom Kapitel 24 erfüllt sein müssen.
  19.  
  20. Nun aber zur Anleitung...
  21.  
  22.  
  23.  
  24. ===========================================================================
  25.  
  26.                            PCQ Version 1.2
  27.                   Ein Pascal-Compiler für den Amiga
  28.                           von Patrick Quaid
  29.  
  30. ===========================================================================
  31.  
  32. PCQ (das bedeutet Pascal Compiler, ähem, Q.... Naja, dem Autor fiel kein Name
  33. ein, so hat er einfach seine Initalien benutzt, ok?) ) ist ein einfacher Pas-
  34. cal-Compiler für den Amiga. Er ist zwar kein Public-Domain-Program im eigent-
  35. lichen Sinne (denn der Autor behält sich das Copyright auf den Sourcecode,
  36. die runtime.library mit deren Sourcecode, den Compiler und der Dokumentation
  37. vor), aber es darf weitergegeben werden, solange der Preis angemessen ist
  38. (siehe auch der letzte Abschnitt).
  39.  
  40. Die Features des Compilers:
  41.  
  42. Das Schlechte:
  43.  
  44. - Er unterstützt keine Sets.
  45. - Er ist nicht kompatibel zu TurboPascal, obwohl er sich immer mehr annähert.
  46. - Manche Sachen sind leicht anders als im Standard-Pascal.
  47. - Die meisten Fehler erzeugen eine Endlosschleife.
  48.  
  49. Das Positive:
  50. - Er funktioniert.
  51. - Der Compiler unterstützt Include-Files
  52. - Er erlaubt externe Kompilierung, obwohl diese von Hand geprüft
  53.       werden müssen (das hier ist kein Modula-2)
  54. - Unterstützt Strukturen (Records), Aufzählungstypen (enumerated types),
  55.       Zeiger (Pointers), Arrays und Strings.
  56. - Typen-Konvertierungen wie in Modula-2 werden unterstützt. Mit anderen
  57.      Worten: Ausdrücke wie "integer('d')" sind möglich. Einige Besonderheiten
  58. - Einige Besonderheiten von Turbo und Quick-Pascal wie "Exit" innerhalb einer
  59.   Prozedur, Operatoren wie "Shl" und "Shr" und Typen-Konstanten sind
  60.   eingebaut worden.
  61. - Es können beliebig viele const, var, type, prcödure und function-Blöcke
  62.   definiert werden, in jeder Reihenfolge.
  63. - Er kostet nichts (solange sie nicht auf gewisse Sonderangebote deutscher
  64.   PD-Händler reinfallen, Anm.d.Ü.).
  65.  
  66.  
  67.  
  68.                         IHNALTSVERZEICHNIS
  69.                         ^^^^^^^^^^^^^^^^^^
  70.  
  71. Diese Bedienungsanleitung sollte mit einem sog. File-Reader, also einem
  72. speziellen ASCII-Datei-Leseprogramm oder einem Text-Editor gelesen werden.
  73. Deshalb hier keine Seiten-, sondern Zeilennummern (ohne Gewähr, Anm.d.Ü. :-)
  74.  
  75. Abschnitt (Sektion)                                             Zeile
  76.  
  77.  1.     Arbeiten mit dem PCQ ..................................  138
  78.  2.     Inkompatibilitäten ....................................  245
  79.  3.     Reservierte Worte .....................................  303
  80.  4.     Pascal-Programm-Struktur ..............................  326
  81.  5.     Vordefinierte Elemente ................................  385
  82.  5. 1   Konstanten (CONST) ....................................  412
  83.  5. 2   Typen (TYPE) ..........................................  505
  84.  5. 3   Variablen (VAR) .......................................  570
  85.  5. 3.1 Standard-Variablen ....................................  592
  86.  5. 4   Prozeduren und Funktionen - Deklarationen .............  641
  87.  5. 4.1 Parameterübergabe .....................................  668
  88.  5. 4.2 Vor-Definition/Referenz von Prozeduren und Funktionen .  702
  89.  5. 4.3 Externe Verweise (Referenzen) .........................  724
  90.  5. 4.4 Prozeduren (PROCEDURE) ................................  743
  91.  5. 4.5 Funktionen (FUNCTION) .................................  881
  92.  6.     Namen (Label) - Deklarationen ......................... 1014
  93.  7.     Spezielle Befehle ..................................... 1031
  94.  8.     Ausdrücke ............................................. 1069
  95.  8. 1.  Berechnungsreihenfolge ................................ 1218
  96.  8. 2.  Konstanten-Ausdrücke .................................. 1247
  97.  8. 3.  Referenz-Variablen .................................... 1256
  98.  9.     Statements ............................................ 1292
  99.  9. 1.  IF-Anweisung .......................................... 1317
  100.  9. 2.  WHILE-Anweisung ....................................... 1346
  101.  9. 3.  REPEAT-Anweisung ...................................... 1368
  102.  9. 4.  FOR-Anweisung ......................................... 1388
  103.  9. 5.  CASE-Anweisung ........................................ 1430
  104.  9. 6.  WITH-Anweisung ........................................ 1466
  105.  9. 7.  COMPOUND-Anweisung .................................... 1499
  106.  9. 8.  ASSIGNMENT-Anweisung .................................. 1512
  107.  9. 9.  PROCEDURE-Aufrufe ..................................... 1524
  108.  9.10.  RETURN-Befehl ......................................... 1551
  109.  9.11.  GOTO-Anweisung ........................................ 1569
  110. 10.     Ein-und Ausgabe ....................................... 1596
  111. 10. 1.  Text- und Typen-Files ................................. 1632
  112. 10. 2.  Öffnen von Files ...................................... 1677
  113. 10. 3.  Schreiben in Files .................................... 1753
  114. 10. 4.  Lesen aus Files ....................................... 1807
  115. 10. 5.  File-Puffer ........................................... 1880
  116. 10. 6.  Ein- und Ausgabe-Überprüfung (IO-Checken) ............. 1934
  117. 10. 7.  Standard Ein & Ausgabe ................................ 1960
  118. 11.     Zeichenkettenvariablen (Strings) ...................... 2023
  119. 11. 1.  Reservieren von String-Speicher ....................... 2055
  120. 11. 2.  Benutzung von Escape-Zeichen .......................... 2099
  121. 11. 3.  StringLib ............................................. 2143
  122. 12.     Speicher-Verwaltung ................................... 2154
  123. 12. 1.  HeapError (Überlauf-Fehler) ........................... 2187
  124. 13.     Exit-Prozeduren ....................................... 2214
  125. 14.     Laufzeitfehler (Runtime-Errors) ....................... 2257
  126. 15.     Compiler-Direktiven ................................... 2318
  127. 16.     Typen-Konvertierungen ................................. 2435
  128. 17.     Kurzer Anfangscode (Small Initialisation Code) ........ 2473
  129. 18.     Externe Files ......................................... 2524
  130. 19.     Einige Anmerkungen für Assembler-Programmierer ........ 2588
  131. 20.     Fehlermeldungen ....................................... 2612
  132. 21.     Quellen ............................................... 2643
  133. 22.     Zukünftige Erweiterungen .............................. 2707
  134. 23.     Update-History ........................................ 2729
  135. 24.     Weitere Anmerkungen, Copyright und Adressen ........... 2738
  136. 25.     Stichwortverzeichnis .................................. 2797
  137. 25. 1.  Allgemeine Begriffe ................................... 2808
  138. 25. 2.  Mathematische Operatoren .............................. 2899
  139. 25. 3.  Compiler-Direktiven ................................... 2923
  140. 26.     Abschließende Kurzinformationen ....................... 2936
  141.  
  142.  
  143.  
  144. 1. Arbeiten mit dem PCQ
  145. ^^^^^^^^^^^^^^^^^^^^^^^
  146.  
  147. Auf dieser Diskette befinden sich eine ganze Menge Files, die Sie sich
  148. vor dem ersten Einsatz des PCQ erst einmal auf eine Arbeitsdiskette
  149. kopieren sollten. Eines davon ist natürlich der Compiler selbst (Pascal),
  150. selbstverständlich ebenso die Laufzeit-Bibliothek (PCQ.lib). Außerdem müßt
  151. Ihr Euch den Assembler (A68k) und den Linker (Blink) ebenso auf Eure Arbeits-
  152. disk kopieren. Diese hier aufgelisteten Files sind sogar für die einfachsten
  153. Programme unbedingt erforderlich.
  154.  
  155. Alle Files mit dem Suffix ".p" sind Pascal-Beispielprogramme, die Ihr
  156. Euch ebenfalls auf Eure Arbeitsdisk kopieren könnt. Der Autor arbeitetet
  157. natürlich wesentlich mehr am Compiler selbst, als an diesen Beispielen,
  158. einige von diesen sind jedoch vor allem für diejenigen von Euch
  159. interessant, die noch nie mit Pascal gearbeitet haben. Diese Programme
  160. demonstrieren alle Möglichkeiten des Compilers, die dem Autor bis dato
  161. eingefallen sind, deswegen solltet Ihr Euch diese Ansehen, bevor Ihr sie
  162. löscht. Der Source-Code des Compilers besteht ebenfalls aus einer Anzahl
  163. Files mit dem Suffix ".p".
  164.  
  165. Alle Files mit dem Suffix ".i" sind Include-Files für einige System-
  166. Bibliotheken. Diese definieren die Typen, Konstanten, Prozeduren,
  167. Funktionen, Variablen und Records, die für System-Zugriffe erforderlich
  168. sind. Diese solltet Ihr nach Möglichkeit mit auf Eure Arbeitsdisk in ein
  169. Unterverzeichnis mit dem Namen "Include" kopieren. Auch einige
  170. Include-Files für Routinen in der "PCQ.lib" gehören dazu. Schauen Sie sich
  171. diese genauer an, da hier öfters etwas geändert wird. Der Code für diese
  172. Routinen ist in der "PCQ.lib".
  173.  
  174. Um nun ein Programm zu compilieren, müssen Sie erst eines mit einem
  175. Texteditor (ich empfehle den AZ-Editor auf der GPD-Disk 40, den Ihr gegen
  176. 3 DM bei Stefan Grad (Adresse s.o.) bekommen könnt - Anm.d.Ü.) schreiben,
  177. oder eines der Beispielprogramme nehmen. Dann geben Sie ein:
  178.  
  179.             1> Pascal prog.p prog.asm {-q}
  180.  
  181. wobei "Pascal" natürlich der Compiler selbst ist (den Namen können Sie
  182. nach belieben ändern). "prog.p" ist der Name der Quell-Datei des
  183. Pascalprogrammes, der natürlich auch beliebig sein kann. Der zweite
  184. Paramter ist dann der Name des zu erzeugenden Assembler-Files. Die "-q"-
  185. Direktive bewirkt, das der Compiler nur noch Fehlermeldungen ausgibt, und
  186. diese in komprimierter Form.
  187.  
  188. Beim Compilieren der Beispielprogramme kann es Probleme mit der Struktur
  189. der Unterverzeichnisse geben. Die Beispiele verlangen alle die
  190. Include-Files in einem Verzeichnis ":Include/BlaBla.i". Falls das Probleme
  191. mit der Ihrer Konfiguratiön aufwirft, müßen Sie die Include-Befehle am
  192. Anfang der Programme ändern.
  193.  
  194. Hat der Compiler keine Fehlermeldung ausgegeben, geben Sie ein:
  195.  
  196.             1> A68k prog.asm prog.o
  197.  
  198. Der Assembler erzeugt dann den Object-Code. Sollte sich auf dieser Diskette
  199. der A68k-Assembler befinden, dann sollten Sie darauf auch die entsprechende
  200. englischsprachige Anleitung zu diesem Assembler finden ("A68k.doc"). Falls
  201. nicht, benutzen Sie die Version V2.6 des A68k-Assemblers von Charlie Gibbs.
  202. Dieser Assembler führt viele kleinere Optimierungen durch, auf die sich
  203. der PCQ mehr oder weniger verlässt. Deshalb kann ich nicht behaupten, daß
  204. der PCQ-Compiler auch mit anderen Assemblern zusammenarbeitet. Am Ende
  205. müssen Sie nun das Programm "Linken", also geben Sie nun ein:
  206.  
  207.             1> Blink prog.o small.lib to prog library PCQ.lib
  208.  
  209. Hier wird nun also endlich die eigentliche ausführbare Datei mit dem Namen
  210. 'prog' erzeugt. Sämtliche Pascal-Laufzeit-Routinen, die Amiga-
  211. System-Routinen und meine eigene, kleine String-Bibliothek sind in der
  212. PCQ.lib enthalten. Sollten manche Namen von Routinen mit denjenigen, mit
  213. denen Sie selbst arbeiten, kollidieren, dann stellen Sie einfach Ihre
  214. eigenen Bibilothek-oder Object-Files in der Blink-Kommandozeile VOR die
  215. PCQ.lib. Sollten Sie noch Fragen zum Linken haben, dann sehen Sie bitte in
  216. der entsprechenden Dokumentation zu Blink mit dem Namen 'Blink.doc' nach,
  217. die sich ebenfalls auf dieser Diskette befindet.
  218.  
  219. Der Autor selbst verwendet die Version 6.7 von "Blink"  und zweifelt auch
  220. hier, ob der PCQ auch mit anderen Versionen oder sogar anderen Linkern
  221. zusammenarbeitet. "Small.lib" ist eine kleine Offsetbibliothek, die von
  222. Matt Dillon geschrieben wurde. Da in "Blink" ein kleiner Fehler existiert,
  223. muß diese Datei als Object-File statt als Bibliothek eingebunden werden.
  224. Dies erhöht aber nicht die Code-Größe des Programms.
  225.  
  226. Statt nun aber immer diese Folge von Befehlen eingeben zu müssen, können
  227. Sie auch die "make"-Batch-Datei aufrufen, die sich ebenfalls auf der
  228. Original-Pascal Diskette befinden müsste und Ihnen die eklige Tipparbeit
  229. abnimmt. Sie sollten sich dieses File jedoch vorher einmal ansehen, denn es
  230. könnte sein, dass Sie den ein oder anderen Pfad an die Verzeichnis-Strukutr
  231. Ihrer Arbeitsdiskette anpassen müssen. Es ist jedoch wichtig, die
  232. geänderte Version der "make"-Datei unbedingt wieder als Script-File
  233. kennzeichen ("protect make +s"), da diese sonst vom AmigaDOS 1.3 oder ARP
  234. nicht als Batch-Datei anerkannt wird. Aufgerufen wird diese dann wie folgt:
  235.  
  236.             1> make prog
  237.  
  238. Dabei wird dann die Datei 'prog.p' automatisch compiliert, assembliert und
  239. anschliessend zur ausführbaren Datei 'prog' gelinkt, ohne dass Sie mehr
  240. eingeben müssen. Sollten Sie in Ihr Programm natürlich andere, gesondert
  241. compilierte Units eingebunden haben, dann müssen Sie diese Batch-Datei
  242. natürlich ändern oder eine neü schreiben. Ich schlage Ihnen vor, daß Sie
  243. sich für jedes Programm, das Sie mehr als einmal compilieren wollen oder
  244. müssen (vor allem in der Entwicklungsphase) eigene Batch-Dateien schreiben,
  245. die natürlich dann andere Namen haben. Sollten Sie damit Schwierigkeiten
  246. haben, dann wenden Sie sich bitte an mich. Ich kann Ihnen dann hoffentlich
  247. eine ausführlichere Antwort auf Ihre Fragen geben.
  248.  
  249.  
  250.  
  251. 2. Inkompatibilitäten
  252. ^^^^^^^^^^^^^^^^^^^^^
  253.  
  254. PCQ-Pascal ist inkompatibel mit dem Standard-Pascal und Turbo-Pascal.
  255. Kurz, diese sind:
  256.  
  257. 1) Sets werden nicht unterstützt.
  258. 2) Die Standard-Pascal-Deklaration von Zeigern auf Records wird nicht unter-
  259.     stützt. Z.B. der folgende Syntax ist im Standard-Pascal erlaubt:
  260.  
  261.     type
  262.         WindowPtr = ^Window;
  263.         Window = record
  264.            NextWindow : WindowPtr;
  265.             ...
  266.  
  267. Dies bricht in der ersten Zeile mit einem "Unknown ID"-Fehler ab. Benutzen
  268. Sie stattdessen folgendes:
  269.  
  270.    type
  271.        Window = record
  272.            NextWindow : ^Window;
  273.            ....
  274.        end;
  275.        WindowPtr = ^Window;
  276.  
  277. 3) Auch variante Records sind immer noch verboten.
  278.  
  279. 4) Der bekannte Syntax, um ein einzelnes Anführungszeichen zu
  280.     erzeugen (''''), wird ebenfalls nicht akzeptiert. PCQ benutzt die
  281.     C-Escape-Funktion: ('\''). Näheres darüber in dem Abschnitt "Strings".
  282.  
  283. 5) Die Art, wie man ein File öffnet, ist anders als im Standard-Pascal, ob-
  284.     wohl es einmal geöffntet im Grunde genommen dieselben Befehle sind.
  285.  
  286. Obwohl PCQ-Pascal nicht dafür gemacht wurde, um Turbo-Pascal kompatibel zu
  287. sein, werden hier trotzdem einmal die wichtigeren Unterschiede näher erklärt
  288. (die natürlich zu den obigen hinzukommen), um die Portierung dieser Programme
  289. einfacher zu machen.
  290.  
  291. 1) PCQ-Pascal behandelt Strings komplett anders als Turbo-Pascal. PCQ-Strings
  292.     sind C-Strings ähnlich, die nicht so einfach manipuliert werden können
  293.     als Turbo-Strings. Tatsächlich sind PCQ-Strings die schwierigsten von al-
  294.     len 3. Sie werden aber in der Strings-Sektion näher erklärt.
  295.  
  296. 2) In einer PCQ-Pascal-Funktion, führt das zuweisen eines Wertes zu einem
  297.     Funktionswert zum Verlassen der Funktion. In Turbo-Pascal wird der Funk-
  298.     tionsname wie eine Write-Only-Variable (nur beschreibbar) behandelt und
  299.     man muß den Exit-Befehl verwenden. Alle Beispiele im Pascal-Report um-
  300.     säumen die Ausgabe, indem sie den Wert als das letzte Statement assignen
  301.     (?!?).
  302.  
  303. 3) Exit verläßt in PCQ das Programm, während es in Turbo die aktuelle Funk-
  304.     tion oder Prozedur verläßt. Turbos "Exit" ist wie PCQs "Return" und Tur-
  305.     bos "Halt" ist wie PCQs "Exit". Alles klar?
  306.  
  307.  
  308.  
  309. 3. Reservierte Worte
  310. ^^^^^^^^^^^^^^^^^^^^
  311.  
  312. Folgende Worte sind beim PCQ reserviert:
  313.  
  314.             and         for         procedure
  315.             array       forward     program
  316.             begin       function    record
  317.             by          goto        repeat
  318.             case        if          return
  319.             const       in          set
  320.             div         label       then
  321.             do          mod         to
  322.             downto      not         type
  323.             else        of          until
  324.             end         or          var
  325.             external    packed      while
  326.             file        private     with
  327.  
  328. Auch nichtimplementierte Wörter sind reserviert!
  329.  
  330.  
  331.  
  332. 4. Pascal-Programm-Struktur
  333. ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  334.  
  335. Die normale Pascal-Programm-Struktur ist wie folgt:
  336.  
  337. <Program> ::= Program <Identifier> ; <Block>.  |
  338.               Program <Identifier> (<Identifier List>); <Block>.
  339.  
  340. <Block>   ::= <Declarations> begin <Statements> end |
  341.               begin <Statements> end
  342.  
  343. <Identifier List> ::= <Identifier> , <Identifier List> |
  344.                       <Identifier>
  345.  
  346. ::= heißt: ist definiert durch
  347. < > heißt: wird irgendwo anders in der Liste definiert
  348. |   trennt zwischen Alternativen
  349. (WICHTIG !!! - Diese Definitionen tauchen in der weiteren Anleitung immer
  350.  wieder auf! - Anm.d.Ü.)
  351.  
  352. Ein Pascal-Programm beginnt somit mit dem Wort "program" gefolgt von einem
  353. Identifier, gefolgt von einem Semikolon, gefolgt von einem Block und einem
  354. Punkt am Ende. Es kann aber auch aus "program", gefolgt von einem Identifier
  355. und einer linken Klammer sowie einer Identifier-Liste und einer rechten Klam-
  356. mer, einem Semikolon, einem Block und schließlich einem Punkt bestehen.
  357.  
  358. Bisher undefiniert sind:
  359.  
  360. <Declarations> ::= <Declaration> , <Declarations> | <Declaration>
  361.  
  362. <Declaration> ::= <Type Declaration>      |
  363.                   <Constant Declaration>  |
  364.                   <Variable Declaration>  |
  365.                   <Label Declaration>     |
  366.                   <Procedure Declaration> |
  367.                   <Function Declaration>
  368.  
  369. Beachtet dabei, daß Standard-Pascal eine Ordnung der Deklarationen verlangt:
  370. Es erwartet einen Konstantenblock, gefolgt von einem Typenblock usw. In PCQ
  371. ist dem nicht so, wodurch Ihr so viel Deklarationen in einer beliebigen Ord-
  372. nung haben könnt, wie Ihr wollt.
  373.  
  374. Dies ist das normale Format eines jeden PCQ-Pascal-Programmes. Es gibt aller-
  375. dings eine Ausnahme (natürlich): die separat kompilierbaren Files. Turbo-Pas-
  376. cal benutzt hierzu eine Unit-Struktur, wodurch man Units schreiben, kompilie-
  377. ren und debuggen kann, um sie anschließend in vielen Programmen zu benutzen.
  378. PCQ bietet eine ähnliche, wenn auch nicht so mächtige, Funktion in der Form
  379. externer Files. Die Struktur:
  380.  
  381. <Program> ::= Program <Identifier>; <Block>.  |
  382.               Program <Identifier> (<Identifier List>); <Block>. |
  383.               External ; <Declarations>
  384.  
  385. Somit muß also ein externes File nur das reservierte Wort "External" gefolgt
  386. von einem Semikolon enthalten, gefolgt von Serien von Prozeduren, Funktionen,
  387. usw. Siehe die Sektion "Externe Files" für mehr Infos.
  388.  
  389.  
  390.  
  391. 5. Vordefinierte Elemente
  392. ^^^^^^^^^^^^^^^^^^^^^^^^^
  393.  
  394. Nachfolgend ist eine Anordnung der Elemente, wie sie in Pascal üblich ist.
  395. Nur könnt Ihr im PCQ diese Blocks in jeder beliebigen Reihenfolge schreiben,
  396. und vor allem mehr als einmal jeden Block definieren. Mit anderen Worten:
  397. Eure Programme können z.B so aussehen:
  398.  
  399.    Program name;
  400.    var
  401.        Variablendeklarationen
  402.    type
  403.        Typen
  404.    var
  405.        mehr Variablen
  406.    procedure
  407.        eine Prozedur
  408.    var
  409.        noch mehr Variablen...
  410.  
  411. Und so weiter... Natürlich muß ein Element nach wie vor erst einmal dekla-
  412. riert werden, bevor es gebraucht wird. Das wurde zugelassen, da es wirklich
  413. übel ist, einen Rattenschwanz von Include-Files zu ordnen (jedes einzelne
  414. Include-File hätte sonst in vier Abschnitte zerlegt werden müssen: In die
  415. Konstanten, die Typen, die Variablen und die Prozeduren und Funktionen).
  416.  
  417.  
  418. 5.1 Konstanten (CONST)
  419. ----------------------
  420.  
  421. Die Konstanten folgen folgender Struktur:
  422.  
  423. <Const Block> ::= Const <Const Declarations>;
  424.  
  425. <Const Declarations> ::= <Const Declaration> |
  426.                          <Const Declaration> ; <Const Declarations>
  427.  
  428. <Const Declaration> ::= <Identifier> = <Constant Expression> |
  429.                         <Identifier> : <Type Specification> =
  430.                                         <Typed Constant Value>
  431.  
  432. <Typed Constant Value> ::= <Constant Expression>      |
  433.                            ( <Constant Expressions> ) |
  434.                            @ <Identifier>
  435.  
  436. Die Werte für True und False werden als -1 und 0 definiert. Nil (Null)
  437. wird definiert als Zeiger mit dem konstanten Wert 0, ist jedoch kein
  438. reserviertes Wort wie im Standard-Pascal.
  439.  
  440. Meist, wenn der Compiler eine Konstante verlangt, nimmt er dafür einen
  441. konstanten Ausdruck (der schon während der Compilierung ausgewertet wird).
  442. Beispielsweise funktioniert Folgendes:
  443.  
  444.    const
  445.        first = 234;
  446.        second = first * 2;
  447.  
  448.    type
  449.        thetype = array [first .. first + 7] of char;
  450.  
  451. Normale Konstanten sind einfach Read-Only-Variablen (nur lesbar), die keinen
  452. Speicher wegnehmen. Der Konstantenwert wird nur im Programm anstatt des Iden-
  453. tifiers eingefügt. Konstanten können vom Typ INTEGER, REAL, CHAR, BOOLEAN,
  454. STRING und ARRAY OF CHAR sein, nicht dagegen benutzerdefinierte Typen bzw.
  455. Record- oder Array-Typen (Feldvariablen).
  456.  
  457. Es gibt einige Unterschiede zwischen diesem und dem TurboPascal-Syntax (na-
  458. türlich alle zum Vorteil des PCQ :-) . Zunächst einmal müssen in Turbo bei
  459. der Definition von Konstanten-Records aus Feld-Identifier, gefolgt von einem
  460. Doppelpunkt, dem Wert und möglicherweise einem Semikolon bestehen. In PCQ
  461. muß hingegen nur dasselbe wie bei Feldern (arrays) gemacht werden: alle
  462. Felder werden mit Kommas getrennt spezifiziert.
  463.  
  464. Bei Turbo bis V6.0 mußten Zeiger-Typen nach NIL: initialisiert werden. PCQ
  465. erlaubt die initialisierung eines Zeigertyps auf Nil oder auf die Adresse
  466. einer globalen Variable oder Typenkonstante. Um dies zu tun, muß man norma-
  467. lerweise den "@"-Operator benutzen, der die Adresse einer spezifizierten Va-
  468. riable zurückgibt.
  469.  
  470. Der letzte Unterschied ist, daß einige typifizierte Konstantenwerte in unter-
  471. sequenten Konstantenausdrücken verwendet werden können. Strukturisierte Typen
  472. (z.B. Records und Arrays) können nicht verwendet werden. Verwendet werden
  473. können also Integer, Real und andere sog. einfachen Typen.
  474.  
  475. Es gibt einige Standard-Konstanten (z.B. die in dem Compiler selbst eingebau-
  476. ten), die man nicht deklarieren oder per Include-File benutzen muß.
  477. Diese sind:
  478.  
  479. False       ist vom Typ Boolean und hat den Wert 0
  480.  
  481. MaxInt      ist als $7FFFFFFF definiert (dezimal 2.147.483.647), der im 32-
  482.             Bit-Integer-Typ "untergebracht" werden kann. Somit kann eine In-
  483.             teger-Variable einen Wert von +MaxInt bis -MaxInt beinhalten.
  484.  
  485. MaxShort    ist die größte Zahl, die im 16-Bit-Kurzzahl-Typ untergebracht
  486.             werden kann. Es ist 32767, oder $7FFF in hex. Eine Short-Variable
  487.             kann also Werte von +MaxShort bis -MaxShort enthalten (d.h. bis
  488.             -(Maxshort+1), weil MaxInt analog ist).
  489.  
  490. Nil         ist eine Konstante vom Typ Adresse. Sie ist wie folgt definiert:
  491.                 Nil=Address(0);
  492.             Im Standard-Pascal ist "Nil" ein reserviertes Wort, was aber
  493.             nicht sein muß. Daher ist es in PCQ auch nicht reserviert!
  494.  
  495. True        ist vom Typ Boolean und hat den Wert -1.
  496.             In manchen Fällen genügt, daß es sich um eine Zahl ungleich Null
  497.             handelt, aber der "not"-Operator verhält sich falsch bei irgend-
  498.             welchen anderen Werten.
  499.  
  500. Eine andere Form von Konstanten sind "Typen-Konstanten". Dies sieht
  501. folgendermassen aus:
  502.  
  503.         CONST
  504.             Identifier : Type Description = Constant Expression;
  505.  
  506. Typenkonstanten werden zu Beginn des Programms mit der "Constant
  507. Expression" initialisiert und können dann genauso wie Variablen benutzt
  508. werden. Dies wird im Abschnitt "Typenkonstanten" genaür beschrieben.
  509.  
  510.  
  511. 5.2 Typen (TYPE)
  512. ----------------
  513.  
  514. Es gibt verschiedene vordefinierte Typen.
  515.  
  516. Integer       4 Bytes, von +/- MaxInt
  517.  
  518. Short         2 Bytes. Zahlen innerhalb des Programmtexts
  519.               werden als Short-Werte angesehen, sofern sie nicht
  520.               grösser als 32767 oder kleiner als - 32767 sind.
  521.  
  522. Byte          1 Byte. Bei diesen drei Typen handelt es sich
  523.               ausnahmslos um numerische Typen, sodaß Sie sie in normalen
  524.               Ausdrücken verwenden können, ohne sich um
  525.               Typenkonvertierungen Gedanken machen zu müssen. Der Compiler
  526.               wandelt die kleinen Werte automatisch auf die verlangte
  527.               Grösse um. Denken Sie aber daran, dass momentan noch kein
  528.               Überlaufgeprüft wird. Ab Version 1.1 haben Byte-Werte den
  529.               Bereich 0..255 statt -128..127.
  530.  
  531. Real          4 Bytes (FFP-Format).
  532.  
  533. Char          1 Byte.
  534.  
  535. Boolean       1 Byte. False ist 0, Trü ist -1.
  536.  
  537. String        4 Bytes. Als "^char" definiert. Wird im
  538.               Abschnitt "Strings" noch näher erläutert.
  539.  
  540. Address       4 Bytes. Dies ist ein Zeiger auf keinen besonderen
  541.               Typ und ist zu jedem anderen Zeiger typenkompatibel
  542.               Tatsächlich ist die Konstante Nil vom Typ Address.
  543.  
  544. Text          32 Bytes. Dies ist nicht das gleiche wie ein "file
  545.               of char". Die normale Eingabe und Ausgabe bezieht
  546.               sich auf Textfiles. In Textfiles können Sie Integer-Zahlen,
  547.               Zeichen, Datenfelder (Arrays) und Strings schreiben bzw.
  548.               lesen. Auch Boolean-Werte können geschrieben werden.
  549.  
  550. Enumerated    1 oder 2 Bytes, je nach Anzahl der Aufzählungen.
  551.  
  552. Wie bereits oben erwähnt, können Sie Arrays, Zeiger, Records und Dateien,
  553. basierend auf den obengenannten Typen verwenden. Auch Synonymtypen sind
  554. einsetzbar (wie "type int = integer;").
  555.  
  556. Beachten Sie ausserdem: Überall, wo Sie einen Typen benötigen, können Sie
  557. eine vollständige Typenbeschreibung verwenden. Einige Compiler haben
  558. hierbei Probleme, und ich bin mir auch nicht sicher, was das Standard-
  559. Pascal in diesem Zusammenhang sagt, aber das ist mir eigentlich auch
  560. ziemlich egal.
  561.  
  562. In Version 1.0 mußten mehrdimensionale Arrays ausgeschrieben werden. Es war
  563. also nicht möglich, folgendes zu schreiben:
  564.  
  565.     Array [0..5, 0..11] of Integer;
  566.  
  567.    Stattdessen mußte folgende Konstruktion benutzt werden:
  568.  
  569.     Array [0..5] of Array [0..11] of Integer;
  570.  
  571.    für die Definition, und "ArrayName[x][y]" im Programm. Da die meisten
  572.    Pascal-Compiler die Abkürzung mit Komma erlauben, ist dies nun auch in
  573.    PCQ möglich.
  574.  
  575.  
  576. 5.3 Variablen (VAR)
  577. -------------------
  578.  
  579. Variablen-Deklarationen werden wie im Standard-Pascal behandelt:
  580.  
  581. <Var Declaration> ::= Var <Var Definitions> ;
  582.  
  583. <Var Definitions> ::= <Var Definition> |
  584.                       <Var Definition> ; <Var Definitions>
  585.  
  586. <Var Definition>  ::= <Identifier List> : <Type Specification>
  587.  
  588. Globale Variablen werden wie statischer Speicher zugewiesen. Alle Variablen,
  589. die innerhalb einer Prozedur oder Funktion deklariert werden, werden im Stack
  590. zugewiesen. Wenn Ihr also re-entante Routinen schreibt, solltet Ihr globale
  591. Variablen vermeiden.
  592.  
  593. Beachtet, daß lokale Variablen (nicht typed Konstanten) entfernt werden, wenn
  594. die Funktion verlassen wird, wodurch diese nachher nicht mehr angesprochen
  595. werden können (z.B. mit einer Zeigervariablen).
  596.  
  597.  
  598. 5.3.1 Standard-Variablen
  599.  
  600. Es gibt diverse Variablen, die in PCQ eingebaut sind. Diese sind immer vor-
  601. handen und verhalten sich wie globale Variablen. Diese sind:
  602.  
  603.       CommandLine   : String;
  604.  
  605. Zeiger auf den Speicher der Kommandozeile, mit der der Benutzer das Programm
  606. geladen hat (ohne Name des Programms und jeglichen Indirection-Parametern).
  607. Falls das Programm von der Workbench gestartet wurde, ist dieser Wert nicht
  608. definiert. Um sicher zu gehen, sollte diese Variable als "Read-only" behan-
  609. delt werden. Macht eine Kopie davon, wenn sie modifiziert werden soll!
  610.  
  611.       ExitProc      : String;
  612.  
  613. Diese Variable zeigt auf die erste Prozedur, die am Programmende aufgerufen
  614. wird, wenn ein Run-Time-Fehler auftritt. Siehe "Exit Procedures" für mehr
  615. Infos.
  616.  
  617.       ExitCode      : Integer;
  618.  
  619. Falls das Programm normal beendet wurde, ist dies 0. Falls Exit()
  620. aufgerufen wurde, ist es das Argument des Aufrufs, ansonsten die Nummer
  621. eines Run-Time-Fehlers, der auch an AmigaDOS übergeben wird.
  622.  
  623.       ExitAddr      : Address;
  624.  
  625. Falls das Programm aufgrund eines Run-Time-Fehlers abgebrochen wurde,
  626. enthält diese Variable die Adresse des Befehls nach dem Fehler.
  627.  
  628.       HeapError     : Address;
  629.  
  630. Enthält die Adresse einer Funktion, die aufgerufen werden so,, wenn New() o.
  631. AllocString() keinen Speicherblock reservieren kann. Siehe die Sektion "Spei-
  632. cher-Verwaltung".
  633.  
  634.       Input         : Text;
  635.  
  636. Es korrespondiert zum Standard-Eingabe-Kanal des Programms, wie z.B. dem CLI,
  637. von dem es aufgerufen wurde. PCQ-Pascal-Programme erwarten eine Art von Stan-
  638. dard-Inputfile, es sei denn, Ihr sagt ihm, das nicht zu tun. Siehe die Sek-
  639. tion "Input/Output".
  640.  
  641.       Output        : Text;
  642.  
  643. Wie Input, nur zum Ausgabe-Kanal. Dies ist in den meisten Fällen der CLI,
  644. von dem es gestartet wurde.
  645.  
  646.  
  647. 5.4 Prozeduren- und Funktionen-Deklarationen
  648. --------------------------------------------
  649.  
  650. Prozeduren und Funktionen erlauben es, allgemeine Routinen mit einem größeren
  651. Block zu definieren. Prozeduren werden durch Procedure-Statements aufgerufen
  652. und Funktionen werden durch die Benutzung in Ausdrücken aufgerufen.
  653. Das Format für Prozeduren- und Funktionen-Definitionen ist:
  654.  
  655. <Proc Declaration> ::= Procedure <Identifier> ; <Body> |
  656.                        Procedure <Identifier>
  657.                                 ( <Formal Params> ); <Body>
  658.  
  659. <Body> ::= <Block> | External | Forward
  660.  
  661. <Formal Params> ::= <Identifier List> : <Type Specification> |
  662.                     var <Identifier List> : <Type Specification>
  663.  
  664. <Func Declaration> ::= Function <Identifier> :
  665.                                    <Type Specification> ; <Body> |
  666.                        Function <Identifier> ( <Formal Params> ) :
  667.                                    <Type Specification> ; <Body>
  668.  
  669. Denkt aber daran, daß Prozeduren nur benutzt werden kann, wo <Statement>
  670. steht (in anderen Struktur-Definitionen, Anm.d.Ü.), während Funktionen nur
  671. bei <Expression> benutzt werden können.
  672.  
  673.  
  674. 5.4.1 Parameterübergabe
  675.  
  676. Pascal bietet 2 verschiedene Arten von Parameterübergabe.
  677.  
  678. Die erste Art nennt sich Wert-Parameter, was der normale Fall ist. Wenn ein
  679. Parameter als Wert übergeben wird, macht der Compiler eine Kopie des Werts
  680. und übergibt diesen der Funktion. Was auch immer die Prozedur oder Funktion
  681. mit dem Wert macht, ist dem Hauptprogramm egal. Es wirkt sich also auf die
  682. Original-Werte nicht aus. Beim Aufruf der Prozedur kann man jeden Ausdruck
  683. (des korrekten Typs) als den aktuellen Parameter übergeben.
  684.  
  685. Die 2. Art sind Referenz-Parameter. Diese werden dadurch erkenntlich gemacht,
  686. indem man dem Parameter das Wort VAR im Prozeduren- oder Funktions-Header
  687. voranstellt. Die Prozedur oder Funktion arbeitet mit den übergebenen Refe-
  688. renz-Parametern, d.h. diese Werte werden verändert und beim Rücksprung aus
  689. der Prozedur/Funktion ans Programm zurückgegeben. D.h. die Variablen enthal-
  690. ten nicht mehr dieselben Werte wie beim Prozedur/Funktions-Aufruf. Referenz-
  691. Parameter müssen als Variablen-Referenzen übergeben werden und können keine
  692. kompletten Ausdrücke sein. Referenzparameter müssen auch eine genauere Typen-
  693. kompatibilität aufweisen als Wert-Parameter, denn eine 4-Byte-Integer-Variab-
  694. le kann nicht in eine 1-Byte-Lücke geschrieben werden.
  695.  
  696. Man sollte also normalerweise Wert-Parameter bevorzugen (was Bugs reduziert),
  697. ausgenommen von 3 Fällen:
  698. 1. der Wert einer Variable SOLL von einer Prozedur/Funktion verändert werden,
  699. 2. der Parameter ist groß (wenn ein Wert-Parameter verwendet wird, muß der
  700.     Compiler erst eine komplette Kopie im Stack davon machen, bevor die Rou-
  701.     tine aufgerufen wird, was Zeit und Stack-Speicher benögt, während der
  702.     Compiler bei einem Referenz-Parameter lediglich die Adresse in den Stack
  703.     bringen muß),
  704. 3. der Parameter ist ein File-Typ (dann MUSS der Parameter als Referenz über-
  705.     geben werden).
  706.  
  707.  
  708. 5.4.2 Vor-Definition/Referenz von Prozeduren und Funktionen
  709.  
  710. In Pascal muß jeder Identifier deklariert werden, bevor er benutzt werden
  711. kann, was Probleme geben kann, wenn Prozeduren oder Funktionen gegenseitig
  712. abhängig sind. Pascal erlaubt daher die vor-definition von Prozeduren und
  713. Funktionen, die weiter unten im Sourcecode voll definiert werden.
  714.  
  715. Eine Vor-Referenz sieht aus wie eine normale Prozedur oder Funktion, hat aber
  716. das reservierte Wort "Forward" direkt nach dem Header. Der Header enthält al-
  717. le Informationen, die der Compiler benötigt, um eine Routine korrekt aufzu-
  718. rufen. Nach dieser "Forward"-Deklaration, kann die Routine benutzt werden.
  719. Wenn die Routine schließlich definiert wird, versichert sich der Compiler,
  720. daß diese mit der früher gegebenen Definition übereinstimmt. D.h., daß die
  721. Anzahl der Parameter und die Parametertypen identisch sein müssen. Bei Funk-
  722. tionen muß auch der Ergebnistyp übereinstimmen.
  723. Die eigentlichen Namen der Parameter können verschieden sein - nur deren An-
  724. zahl, Ordnung und Typ werden verglichen.
  725.  
  726. Eine Vor-Referenz muß im selben Block aufgelöst werden, wie sie deklariert
  727. wurde. Dieselbe Routine kann nicht mehr als 1 Mal "forward"-referenzt werden.
  728.  
  729.  
  730. 5.4.3 Externe Verweise (Referenzen)
  731.  
  732. Externe Referenzen sind ähnlich wie Forward-Referenzen - sie sind Deklaratio-
  733. nen von Routinen, die nicht voll definiert sind.
  734. Der Unterschied aber ist, daß Forward-Referenzen später im selben Programmfi-
  735. le definiert werden müssen, während externe Referenzen überhaupt nicht im
  736. Sourcefile definert werden.
  737.  
  738. Die Deklaration von externen Referenzen ist identisch zu den Forward-Referen-
  739. zen, mit der Ausnahme, daß das reservierte Wort "External" anstatt von "For-
  740. ward" benutzt wird.
  741.  
  742. Externe Referenzen dienen zu 2 Hauptzwecken. Zuerst einmal erlauben sie die
  743. Benutzung von Prozeduren und Funktionen in externen Files. Alle Systemrouti-
  744. nen sind in den Include-Files deklariert, die eigentlich in externen Files
  745. definiert sind. Sie erlauben auch den Aufruf von Routinen, die in einer an-
  746. deren Sprache compiliert wurden. Siehe auch die Sektion "Externe Files".
  747.  
  748.  
  749. 5.4.4 Prozeduren (PROCEDURE)
  750.  
  751. Es gibt diverse Standard-Prozeduren, die im PCQ-Pascal integriert sind. Dazu
  752. gehören:
  753.  
  754. (zum Syntax der Funktionen wäre noch zu sagen, daß immer zunächst "procedure"
  755.  angegeben wird, dann der Name der Prozedur mit den Übergabeparametern in
  756.  Klammern. VAR bedeutet eine Referenz-Variable, fehlt VAR, handelt es sich um
  757.  eine Wert-Variable. Hinter dem Doppelpunkt steht der Typ, von dem die Varia-
  758.  ble sein muß. Zur Verdeutlichung nehmen wir mal den 1. Syntax: Im Programm-
  759.  text müßte dann z.B. Close(Datei) stehen, wobei Datei jeder Filetyp sein
  760.  kann)
  761.  
  762.       procedure Close(FileVariable : jeder Filetyp);
  763.  
  764. Dies entfernt die Filevariable und alle Systemresourcen, die dazu benutzt
  765. wurden, um das File offenzuhalten. Siehe auch "Ein/Ausgabe"
  766.  
  767.       procedure Dec(v : jede Ordnungszahl(variable) oder Zeiger);
  768.            oder Dec(v, Menge : Integer);
  769.  
  770. Dec (Kürzel für Decrement) zieht 1 (oder mehr) von einer Variablen ab.
  771. "Dec(x,n)" entspricht "x:=x-n", ist aber leicht effizienter. Die Variable
  772. muß entweder eine Ordnungszahl (wie Char, Byte, Integer, usw.) oder ein Zei-
  773. ger sein. Der optionale Mengen-Parameter muß ein Integer-Typ sein - fehlt
  774. dieser, wird der 1. Wert geschätzt...
  775. Ist die Variable ein Ordnungszahl-Typ, wird der Wert normal abgezogen. Ist
  776. die Variable jedoch ein Zeiger, multipliziert Dec() den Wert mit der Größe
  777. des Typs, auf den der Zeiger zeigt, multipliziert, d.h. wenn man einen Zei-
  778. ger p des Typs ^Integer hat, zeiht Dec(p) im Endeffekt 4 vom Zeiger ab.
  779.  
  780.       procedure Dispose(var x : Zeigervariable);
  781.  
  782. Dies gibt den zugeordneten Speicher zurück ans System. Siehe auch "Speicher-
  783. verwaltung".
  784.  
  785.       procedure Exit;
  786.            oder Exit(error : Integer);
  787.  
  788. Exit() unterbricht ein Programm vorzeitig und ist damit die einzig
  789. akzeptable Methode, ein Programm zu verlassen. Dabei wird der gleiche
  790. Vorgang wie beim normalen Abbruch eines Programms vollzogen und dann die
  791. Fehlernummer, die Sie übergeben, ans AmigaDOS übergeben. Diese Routine
  792. gibt den gesamten Speicher frei und schliesst die geöffneten Dateien. Die
  793. Fehlernummer sollte Null sein, wenn das Programm korrekt abgeschlossen
  794. wurde, 5 bei einer Warnung, 10 bei einem Fehler, und 20 bei einem
  795. katastrophalen Fehler.
  796. Exit ist die systemsichere Art ein Programm abzubrechen - auf die DOSExit-
  797. Routine von AmigaDOS sollte möglichst nicht zurückgegriffen werden. Wenn man
  798. Exit aufruft, werden alle Exit-Prozeduren in der Reihenfolge abgearbeitet.
  799. Dazu gehört die Standard-Routine, die alle geöffneten Files schließt und den
  800. Speicher und alles andere, was man definiert hat, freigibt.
  801.  
  802.       procedure Get(var FileVariable : FileTyp);
  803.  
  804. Dies bewegt den File-Zeiger auf das nächste Element des Files, ohne dabei ein
  805. Element einzulesen. Das Element im Filepuffer kann mit dem FileVariable^ Syn-
  806. tax erreicht werden. Siehe auch "Ein/Ausgabe".
  807.  
  808.       procedure Inc(VarReference : Ordnungszahl oder Zeiger);
  809.            oder Inc(VarReference : Ordnungszahl oder Zeiger, Wert : Integer);
  810.  
  811. Inc() addiert einen Integer-Wert zur Variable VarReference. Wenn kein Wert
  812. spezifiziert ist, wird 1 addiert. Falls die Variable ein Ordnungszahltyp ist,
  813. wird die Addition normal ausgeführt. Ist sie allerdings ein Zeiger, wird der
  814. Wert zuerst mit der Größe des Objekts, auf das der Zeiger zeigt, multipli-
  815. ziert, d.h. wenn p ein Zeiger auf einen Integer-Typ ist, wird 4 zu p addiert
  816. (die Größe eines Integers in Bytes).
  817.  
  818.       procedure New(var x : Zeigervariable);
  819.  
  820. Diese allokiert (d.h. reserviert) Speicher für den Platz des Variablentypes
  821. und speichert die Adresse in x. Siehe auch "Speicherverwaltung".
  822.  
  823.       procedure Put(var FileVariable : bel. File-Typ);
  824.  
  825. Dies verschiebt den Filezeiger hinter dem aktuellen Element und schreibt das
  826. aktuelle Element auf die Disk, wenn notwendig. Das aktuelle Element kann mit
  827. Hilfe des FileVariable^ Syntax gesetzt werden. Siehe auch "Ein/Ausgabe".
  828.  
  829.       procedure Read(var FileVariable : Text oder File, Var-Referenzen...);
  830.  
  831. Dies liest Informationen aus einem AmigaDOS-File. Die Filevariable ist op-
  832. tional und die Prozedur ist eine der ganz wenigen in Pascal, die eine variab-
  833. le Anzahl an Argumenten hat. Siehe auch "Ein/Ausgabe".
  834.  
  835.       procedure Readln(var FileVariable : Text, Variablen-Referenzen...);
  836.  
  837. Dies ist identisch mit "Read", mit den folgenden Ausnahmen:
  838. - es kann nur bei Textfiles benutzt werden,
  839. - es kann nur benutzt werden, nachdem alle benötigten Argumente gelesen wur-
  840.     den,
  841. - es liest alle Buchstaben bis zum Beginn der nächsten Zeile.
  842. Siehe auch "Ein/Ausgabe".
  843.  
  844.       procedure Reset(var FileVar : File oder Text;
  845.                          FileName : String;
  846.                        BufferSize : Integer);
  847.  
  848. Dies öffnet ein File zum Lesen. Der BufferSize-Parameter ist optional.
  849. Wenn Ihr die {$I-} Direktive zum manuellen IO-Checken benutzt habt, solltet
  850. Ihr IOResult überprüfen, um das File korrekt geöffnet wurde. Wenn Ihr aber
  851. automatisches IO-Überprüfen benutzt, bricht das Programm mit einem Runtime-
  852. Error ab, wenn das File nicht korrekt geöffnet wird. Siehe auch "Ein/Ausga-
  853. be".
  854.  
  855.       procedure Rewrite(var FileVar : File oder Text;
  856.                            FileName : String;
  857.                          BufferSize : Integer);
  858.  
  859. Dies öffnet ein File zur Ausgabe, indem es alle existierenden Files desselben
  860. Namens löscht. Das BufferSize-Argument ist optional. Falls das File nicht ge-
  861. öffnet werden kann, liefert IOResult einen Wert ungleich 0. Wenn Ihr automa-
  862. tisches IO-Checken benutzt, bricht das Programm mit einem Runtime-Error ab.
  863. Siehe auch "Ein/Ausgabe".
  864.  
  865.       procedure Trap(num : Integer);
  866.  
  867. Diese Prozedur kann von versch. Debuggern als eine Art automatische Abbrech-
  868. marke benutzt werden. Wenn Ihr also die korrekte "Trap" (zu deutsch: Falle)
  869. benutzt, könnte der Debugger hier stoppen - oder auch nicht :-) .
  870.  
  871.       procedure write(FileVariable : Text oder File, Ausdrücke...);
  872.  
  873. Dies gibt Informationen in einem AmigaDOS-File aus. Die Filevariable ist op-
  874. tional; es können eine variable Anzahl Argumente übergeben werden. Siehe auch
  875. "Ein/Ausgabe".
  876. (im Grunde genommen ist "write" das Gegenstück zu "read" - Anm.d.Ü.)
  877.  
  878.       procedure writeln(FileVariable : Text, Ausdrücke...);
  879.  
  880. Writeln ist identisch zu write, mit den folgenden Ausnahmen:
  881. - es kann nur bei Textfiles benutzt werden,
  882. - am Ende der Argumente, die von Writeln ausgegeben werden, wird die Zeile
  883.     beendigt.
  884. Siehe auch "Ein/Ausgabe".
  885.  
  886.  
  887. 5.4.5 Funktionen (FUNCTION)
  888.  
  889. Es gibt ein paar in dem Pascal-Compiler eingebaute Funktionen. Diese wären:
  890.  
  891. (zum Syntax der Funktionen wäre noch zu sagen, daß zunächst "function", dann
  892.  der Funktionsname mit Übergabeparametern in Klammern, gefolgt von einem
  893.  Doppelpunkt und dem Funktionstyp angegeben ist. VAR x bedeutet dabei eine
  894.  Referenz-Variable, x eine Wert-Variable. Hinter dem Doppelpunkt steht, von
  895.  welchem Typ die Variable sein muß. Nehmen wir zur Verdeutlichung das 1. Bei-
  896.  spiel. Hier könnte z.B. im Programm x:=adr(var y) stehen. Das würde die Ad-
  897.  resse der Variablen y in x speichern. Dabei muß x vom Typ Adresse sein, wäh-
  898.  rend der Typ von y hier egal ist. Anm.d.Ü.)
  899.  
  900.       function adr(var x : jede Variable): Address;
  901.          übergibt die Adresse von x (entspricht Addr() in Turbo); es kann
  902.          auch der Operator @ benutzt werden.
  903.  
  904.       function abs(x : numerischer Typ) : der gleiche Typ;
  905.          Übergibt den absoluten Wert (d.h. den Wert der Variablen ohne Vor-
  906.          zeichen).
  907.  
  908.       function arctan(x : numerischer Typ) : real;
  909.          übergibt den ungefähren Arctangens des Parameter in Radianten.
  910.  
  911.       function Bit(t : Integer) : Integer;
  912.          übergibt die Zahl, die der Bit-Position entspricht.
  913.  
  914.       function chr(x : numerischer Typ) : char;
  915.          verwandelt jeden numerischen Typ in den zugehörigen ASCII-Charakter.
  916.          (z.B. writeln(chr(65)) liefert "A" - Anm.d.Ü.)
  917.  
  918.       function ceil(x : real): real;
  919.          übergibt die kleinste Ganzzahl größer oder gleich x.
  920.  
  921.       function cos(x : numerischer Typ in Radianten) : real;
  922.          übergibt den Cosinus dew angegebenen Winkels in Radianten.
  923.  
  924.       function eof(x : jedes File) : boolean;
  925.          Übergibt true, falls Sie sich am Ende einer Input-Datei
  926.          befinden. Ansonsten wird false übergeben. Siehe auch "Ein/Ausgabe".
  927.  
  928.       function exp(x : numerischer Typ) : real;
  929.          übergibt e hoch x, wobei e rund 2,71828 ist.
  930.  
  931.       function float(x : integer, short oder byte) : real;
  932.          verandelt x in eine Fließkommazahl. Falls die Integer-Zahl ziemlich
  933.          groß ist, wird sie evtl. gerundet. Somit ist "Trunc(Float(IntVar)) =
  934.          IntVar" nicht immer richtig (trunc ist die "Gegenfunktion zu float,
  935.          Anm.d.Ü.).
  936.  
  937.       function floor(x : real): real;
  938.          übergibt die größte Ganzzahl kleiner oder gleich x.
  939.  
  940.       function IOResult : Integer;
  941.          überprüft, ob seit der letzten Überprüfung Fehler aufgetreten sind.
  942.          Normalerweise fügt PCQ-Pascal Statements ein, um das IO-Ergebnis au-
  943.          tomatisch zu prüfen, was man aber mittels der {$I-} Direktiven ab-#
  944.          schalten kann. Danach muß man dieses aber selbst überprüfen. Das Er-
  945.          gebnis wird bei der Überprüfung gelöscht. Wenn es also weiterbenutzt
  946.          werden soll, muß es in einer Variablen gespeichert werden. S.a. der
  947.          Abschnitt "Ein/Ausgabe".
  948.  
  949.       function ln(x : numerischer Typ) : real;
  950.          übergibt den natürlichen Logarithmus (z.B. zur Basis e) des Parame-
  951.          ters.
  952.  
  953.       function odd(x : numerischer Typ) : boolean;
  954.          Übergibt true, falls x ungerade ist, und ansonsten false.
  955.  
  956.       function open(fname       : String;
  957.                     var fvar    : File oder Text;
  958.                     BufferSize  : Integer) : Boolean
  959.          diese Funktion entspricht der Rewrite-Prozedur. Sie öffnet ein File
  960.          zur Ausgabe und löscht dabei jedes existierende File mit demselben
  961.          Namen. Falls das File korrekt geöffnet werden kann, übergibt Open
  962.          den Wert true. Falls nicht, false. Der BufferSize-Parameter ist op-
  963.          tional. Siehe auch "Ein/Augabe".
  964.  
  965.       function ord(x : jeder Ordinaltyp): integer;
  966.          Übergibt den ordinalen Wert des Arguments als Integer-Zahl, d.h.
  967.          Chars, Booleans usw. werden in ihre numerischen Equivalente verwan-
  968.          delt.
  969.  
  970.       function pred(x : ordinaler Typ) : der gleiche Typ;
  971.          Übergibt die nächstkleinere Ordnungszahl vom selben Typ. So ist z.B.
  972.          Pred(2) 1. Falls das Argument der kleinste Wert desselben Typs ist
  973.          (wie z.B. Pred(a), wenn a=0 und eine Byte-Variable ist), ist sein
  974.          Verhalten undefiniert.
  975.  
  976.       function ReOpen(fname     : String;
  977.                       var fvar  : File oder Text;
  978.                       buffersize: Integer) : Boolean
  979.          Funktionsform von Reset. Öffnet ein File zum Lesen und gibt True
  980.          zurück, falls alles ok ist. Wenn nicht, wird False zurückgegeben.
  981.          Der BufferSize-Parameter ist optional und kann jeden Wert besitzen.
  982.          Siehe auch "Ein/Ausgabe".
  983.  
  984.       function round(x: real) : integer;
  985.          rundet einen reellen Wert zum nächsten Integer. Es ist im Grunde ge-
  986.          nommen Trunc(Wert+0.5). Daher läuft diese Funktion etwas langsamer
  987.          ab als die Trunc-Funktion.
  988.  
  989.       function sin(x: numerischer Typ in Radianten) : real;
  990.          berechnet den Sinus für einen gegebenen Winkel gemessen in Radian-
  991.          ten.
  992.  
  993.       function SizeOf(t : Typenidentifier) : Integer;
  994.          übergibt die Größe des spezifierten Typen. Beachtet, daß der Typ als
  995.          einzelner Identifier spezifiziert werden muß.
  996.  
  997.       function sqr(x : numerischer Typ) : selber Typ;
  998.          berechnet x*x (x²).
  999.  
  1000.       function sqrt(x : numerischer Typ) : real;
  1001.          berechnet die Quadratwurzel von x, d.h. Sqrt(x) * Sqrt(x) = x.
  1002.  
  1003.       function succ(x : ordinaler Typ) : der gleiche Typ;
  1004.          übergibt die nächstgrößere Ordnungszahl desselben Typs. Falls dieser
  1005.          Wert nicht definiert ist (z.B. Succ(n), wenn n der größte Wert eines
  1006.          Typs ist), ist die Funktion nicht definiert.
  1007.  
  1008.       function tan(x : numerischer Typ in Radianten) : real;
  1009.         übergibt den Tangens des Winkels gemessen in Radianten. Falls der Pa-
  1010.         rameter ein ungerades Vielfaches von Pi/2 ist, ergibt diese Funktion
  1011.         bedeutungslose Werte (die Tangens-Funktion ist an ungeraden Vielfa-
  1012.         chen von Pi/2 undefiniert!).
  1013.  
  1014.       function trunc(x : real) : integer;
  1015.          übergibt den Ganzzahlanzeil einer Fließkommazahl. Dies ist der
  1016.          schnellste Weg, eine reelle Zahl in eine Integer-Zahl zu verwandeln.
  1017.  
  1018.  
  1019.  
  1020. 6. Namen (Label)-Deklarationen
  1021. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  1022.  
  1023. Namen müssen in der Deklarationen-Sektion deklariert werden, bevor sie im
  1024. Programm benutzt werden können. Die Namen-Deklaration hat die folgende Form:
  1025.  
  1026. <Label Declarations> ::= Label <Identifiers> ;
  1027.  
  1028. <Identifiers> ::= <Identifier> | <Identifier> , <Identifiers>
  1029.  
  1030. Beachtet, daß Standard- und Turbo-Pascal für Labels auch numerische Werte er-
  1031. laubt, während PCQ-Pascal lediglich normale Identifier erlaubt. Wenn Ihr also
  1032. ein Programm portiert habt, müßt Ihr vor den Zahlen einen (oder mehrere)
  1033. Buchstaben vor die Zahlen platzieren, um die Identifier zu legalen zu machen.
  1034.  
  1035.  
  1036.  
  1037. 7. Spezielle Befehle
  1038. ^^^^^^^^^^^^^^^^^^^^
  1039.  
  1040. Zunächst unterstützt der PCQ If-, While-, Repeat-, For-,  Case-,
  1041. Goto- und With- Befehle.
  1042.  
  1043. Die If-, While- und Repeat-Befehle arbeiten ziemlich so, wie sie
  1044. sollten. Der Case-Befehl entspricht jetzt mehr dem Standard-Pascal als in
  1045. V1.0. Hier einige Beispielausdrücke:
  1046.  
  1047.     case Letter of                   case Number * 5 of
  1048.         'a'      : statement1;          -MaxInt..0 : statement1;
  1049.         'b'..'g' : statement2;          1..MaxInt  : statement2;
  1050.         'j',                         end;
  1051.         'm'..'o',
  1052.         'h'      : statement3;
  1053.     else
  1054.         statement4;
  1055.     end;
  1056.  
  1057. Der For-Befehl unterstÜtzt "downto", was das Inkrement von 1 auf -1 ändert.
  1058. Er unterstÜtzt auch "by" und erlaubt Ihnen damit, die Schrittweite
  1059. festzulegen. Das Argument des "by"-Teils kann jeder reguläre Ausdruck sein,
  1060. fÜr negative Schrittweitn mÜssen Sie aber "downto" statt "to" benÜtzen,
  1061. oder die Schleife wird nur einmal ausgefÜhrt. Nebenbei bemerkt laufen
  1062. For-Schleifen immer mindestens einmal ab. In jedem Fall sieht die Syntax
  1063. ungefähr folgendermassen aus:
  1064.  
  1065.       for <Variable> := <Ausdruck> to|downto <Ausdruck>
  1066.                          [by <Ausdruck>]  do <Befehl>;
  1067.  
  1068. Der letzte Befehl ist "return", der einfach eine PROCEDURE frühzeitig
  1069. abbricht. Eine FUNCTION können Sie vorzeitig abbrechen, indem Sie den
  1070. Funktionsnamen einem Wert zuordnen; "return" funktioniert also nur bei
  1071. Prozeduren.
  1072.  
  1073.  
  1074.  
  1075. 8. Ausdrücke
  1076. ^^^^^^^^^^^^
  1077.  
  1078. Der Compiler akzeptiert den normalen Ausdrucks-Syntax, wie die meisten
  1079. anderen Pascal-Dialekte.
  1080.  
  1081. Folgende Konstanten werden dabei von PCQ akzeptiert:
  1082.  
  1083. (digit heißt Ziffer, binary = binär, hex = hexadezimal, ASCII char = ASCII-
  1084.  Zeichen, char value = Zeichen-Wert, Const = Konstante - Anm.d.Ü.)
  1085.  
  1086. <digit>         ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
  1087.  
  1088. <digits>        ::= <digit> | <digit> <digits>
  1089.  
  1090. <binary digit>  ::= 0 | 1
  1091.  
  1092. <binary digits> ::= <binary digit> |
  1093.                     <binary digit> <binary digits>
  1094.  
  1095. <hex digit>     ::= <digit> | a | b | c | d | e | f
  1096.  
  1097. <hex digits>    ::= <hex digit> | <hex digit> <hex digits>
  1098.  
  1099. <Float Const>   ::= <digits> . <digits>
  1100.  
  1101. <Integer Const> ::= <digits> | $ <hex digits> | % <binary digits>
  1102.  
  1103. <Char Value>    ::= <ASCII char> | \ <escape sequence>
  1104.  
  1105. <Char Values>   ::= <Char Value> | <Char Value> <Char Values>
  1106.  
  1107. <Number Const>  ::= <Integer Const> | <Float Const>
  1108.  
  1109. <Char Const>    ::= ' <Char Value> '
  1110.  
  1111. <String Const>  ::= " <Char Values> "
  1112.  
  1113. <Char Array Const> ::= ' <Char Values> '
  1114.  
  1115. Das mag vielleicht etwas verwirrend sein, daher hier eine nähere Erklärung.
  1116. Es heißt, daß immer wenn der Compiler ein "Integer" erwartet, kann man zwi-
  1117. schen dezimaler, hexadezimaler und binärer Darstellung wählen. Außerdem müs-
  1118. sen Fließkommakonstanten nur in der normalen 23.23 Form erkannt werden - ohne
  1119. Exponenten. Schließlich können auch Escape-Sequenzen in der Art von C für je-
  1120. de Textkonstante benutzt werden. Diese Escape-Werte werden in der "Strings"-
  1121. Sektion (Zeichenketten) beschrieben.
  1122.  
  1123. Wie sind nun diese Sachen in komplette Ausdrücke gegliedert?
  1124. Ok, hier sind die Definitionen:
  1125.  
  1126. (expression heißt Ausdruck, simple = einfach, rel op = Vergleichsoperanden,
  1127.  add op = Additionsoperanden, mul op = Multiplikationsoperanden, factor =
  1128.  Faktor, number const = numerische Konstante, Char Const = Zeichenkonstante,
  1129.  Sting Const = Stringkonstante, Array = Feld, Variable Reference = Referenz-
  1130.  Variable, Function call = Funktionsaufruf)
  1131.  
  1132. <expression> ::= <simple> <rel op> <simple> | <simple>
  1133.  
  1134. <rel op>     ::= = | <> | < | > | <= | >=
  1135.  
  1136. <simple>     ::= <term> <add op> <term> | <term>
  1137.  
  1138. <add op>     ::= + | - | or | xor
  1139.  
  1140. <term>       ::= <factor> <mul op> <factor> | <factor>
  1141.  
  1142. <mul op>     ::= * | / | div | mod | and | shr | shl
  1143.  
  1144. <factor>     ::= <Number Const>         |
  1145.                  <Sign> <Number Const>  |
  1146.                  <Char Const>           |
  1147.                  <String Const>         |
  1148.                  <Char Array Const>     |
  1149.                  <Variable Reference>   |
  1150.                  @ <Variable Reference> |
  1151.                  not <factor>           |
  1152.                  ( <Expression> )       |
  1153.                  <Function call>
  1154.  
  1155. Alles klar? - Nein?! - Ok, das alles heißt, daß Ausdrücke aus Faktoren auf-
  1156. gebaut sind, die Grundblöcke eines Ausdrucks. Ein Faktor kann dabei eine Kon-
  1157. stante oder Variable, ein Ausdruck in Klammern und alle anderen oben aufge-
  1158. führten Sachen sein. Die folgenden Beispiele sind alles Faktoren:
  1159.  
  1160.                                 23
  1161.                            (4.0 - 2.3)
  1162.                             %01000001
  1163.                                'a'
  1164.                      RecordPtr^.Field1[45,23]
  1165.                               @Var1
  1166.                             Abs(Var2)
  1167.  
  1168. Faktoren können auch Operatoren haben, die sich nur für 1 Wert verwenden las-
  1169. sen (im Gegensatz zu binären Operatoren, die für 2 verwendbar sind). Diese
  1170. sind:
  1171.  
  1172.     @   Operator für Adresse-von. Übergibt die Adresse der Referenz-Variablen
  1173.         direkt danach. Entspricht der Adr() Funktion.
  1174.     -   Negation. Nimmt den negativen Wert des folgenden Faktors.
  1175.     +   Bewirkt im Prinzip nichts.
  1176.     not Boolean oder bitweise Negation. Boolean-Faktoren werden zum Gegenteil
  1177.         und Integer-Faktoren werden bitweise umgedreht.
  1178.  
  1179. Diese Faktoren werden in Terme eingebaut. Terme sind entweder dasselbe wie
  1180. Faktoren oder 2 Faktoren mit einem Multiplikationsoperator dazwischen. Die
  1181. Multiplikationsoperatoren sind folgende:
  1182.  
  1183.     *   Multiplikation (mal).
  1184.     /   Fließkommadivision (geteilt). Beide Argumente werden vor der Durch-
  1185.         führung der Berechnung in Fließkommavariablen konvertiert.
  1186.     div Integer-Division. Beide Argumente dieses Operators werden zuerst in
  1187.         Integer verwandelt.
  1188.     mod berechnet den Rest. Beide Argumente werden zuerst nach Integer kon-
  1189.         vertiert (wenn nötig).
  1190.     and logische AND-Funktion.
  1191.     shl schiebt das linke Argument um n Bitpositionen nach links (1 shl
  1192.         5 = 32; 32 ist binär 100000 - Anm.d.Ü.)
  1193.     shr Schiebt nach rechts. Es wird logisch, nicht aritmethisch verschoben,
  1194.         so ergeben negative Werte positve Resultate. Bei diesen Werten muß,
  1195.         um ein vernünftiges Ergebnis zu erhalten, auf "div" zurückgegriffen
  1196.         werden.
  1197.  
  1198. Terme sind in einfache Ausdrücke eingebaut. Einfache Ausdrücke sind entweder
  1199. dasselbe wie Terme oder 2 Terme getrennt mit einem Additionsoperator. Diese
  1200. wären:
  1201.  
  1202.     +   addiert die beiden Operanden.
  1203.     -   subtrahiert die beiden Operanden.
  1204.     or  logisches OR (oder).
  1205.     xor exklusives OR (oder).
  1206.  
  1207. Diese einfachen Ausdrücke werden in kompletten Ausdrücken eingebaut.
  1208. Ausdrücke sind entweder dasselbe wie einfache Ausdrücke oder 2 einfache Aus-
  1209. drücke getrennt mit einem relativen Operator. Diese Operatoren produzieren
  1210. Boolean-Ergebnisse, und werden wie folgt definiert.
  1211.  
  1212.     =   übergibt TRUE falls die beiden Argumente gleich sind.
  1213.     <>  übergibt TRUE falls die beiden Argumente ungleich sind.
  1214.     >   übergibt TRUE falls das linke Argument größer als das rechte Argument
  1215.         ist.
  1216.     <   übergibt TRUE falls das linke Argument kleiner als das rechte Argu-
  1217.         ment ist.
  1218.     >=  übergibt TRUE falls das linke Argument größer oder gleich dem rechten
  1219.         Argument ist
  1220.     <=  übergibt TRUE falls das linke Argument kleiner oder gleich dem rech-
  1221.         ten Argument ist.
  1222.  
  1223.  
  1224. 8.1 Berechnungsreihenfolge
  1225. --------------------------
  1226.  
  1227. Die normalen mathemat. Regeln werden von PCQ auch so behandelt. Die einfachen
  1228. (unary) Operatoren werden zuerst berechnet, dann kommen alle multiplikativen
  1229. Operationen, danach die additiven Operationen und schließlich die relativen
  1230. Operationen. Die Vorrangigkeit sieht somit wie folgt aus:
  1231.  
  1232.         Operator            Vorrangigkeit
  1233.       -------------------------------------
  1234.         @,not,unary +/-     erste (höchste)
  1235.  
  1236.         *,/,div,mod,
  1237.         and,shr,shl         zweite
  1238.  
  1239.         +,-,or,xor          dritte
  1240.  
  1241.         =,<>,<,>,>=,<=      vierte (letzte)
  1242.  
  1243. Alle Ausdrücke in Klammern werden natürlich zuerst berechnet. 2 oder mehr
  1244. Operatoren des gleichen Ranges werden von links nach rechts berechnet (z.B.
  1245. "x+y+z" wird als "(x+y)+z" berechnet).
  1246.  
  1247. (Es sollten hier vielleicht noch ein paar weitere Rechenbeispiele gegeben
  1248.  werden: bei "x+y*z" wird zuerst y*z berechnet und dann x addiert. Das kann
  1249.  mittels (x+y)*z verhindert werden; für Leute, die sich damit auskennen,
  1250.  war dies zwar unnötig - aber es gibt halt auch noch andere... - Anm.d.Ü.)
  1251.  
  1252.  
  1253. 8.2 Konstanten-Ausdrücke
  1254. ------------------------
  1255.  
  1256. Konstantenausdrücke sind dasselbe wie normale Ausdrücke; sie müssen lediglich
  1257. beim Compilieren komplett berechnet werden. Daher können sie keine externen
  1258. Funktionen oder Reference-Variablen benutzen. Benutzt werden können aller-
  1259. dings alle Operatoren wie in Standard-Funktionen.
  1260.  
  1261.  
  1262. 8.3 Referenz-Variablen
  1263. ----------------------
  1264.  
  1265. Referenz-Variablen können schrecklich komplex werden. Der Grund-Syntax sieht
  1266. wie folgt aus:
  1267.  
  1268. (Variable Reference = Referenzvariable, Field = Feld, der Rest dürfte wohl
  1269.  klar sein - Anm.d.Ü.).
  1270.  
  1271. <Variable Reference> ::= <Variable Mark> |
  1272.                          <Variable Mark> <Selectors>
  1273.  
  1274. <Variable Mark> ::= <Variable ID> |
  1275.                     <Type ID> ( <Variable Reference> )
  1276.  
  1277. <Selectors>  ::= <Selector> | <Selector> <Selectors>
  1278.  
  1279. <Selector>   ::= ^ | .<Field Id> | [ <Index Expressions> ]
  1280.  
  1281. Eine Referenz-Variable besteht also aus dem Identifier einer globalen oder
  1282. lokalen Variable, gefolgt von einer beliebigen Anzahl von Selektoren in allen
  1283. möglichen Kombinationen. Die andere Möglichkeit, die sich etwas von der V1.2
  1284. des Compilers unterscheidet, ist, daß Ihr ein "Type-Cast" irgendwo in der
  1285. Mitte von alledem platzieren könnt. Die folgenden Variablen sind alle Refe-
  1286. renz-Variablen:
  1287.  
  1288.         Var1
  1289.         Var1^
  1290.         Var1^.Field1[34,56]
  1291.         Type2(Var1)^.Field2^^[23]
  1292.  
  1293. Wenn Ihr damit anfangt, Programmcode wie diesen zu schreiben, solltet Ihr
  1294. einmal Pause machen...
  1295.  
  1296.  
  1297.  
  1298. 9. Statements
  1299. ^^^^^^^^^^^^^
  1300.  
  1301. Statements sind das Fleisch und die Kartoffeln der Programme - sie sind das,
  1302. was zwischen BEGIN und END. steht (also das Programm an sich - Anm.d.Ü.).
  1303. Sie haben die folgende Form:
  1304.  
  1305. <Statement>   ::= <If Statement>         |
  1306.                   <While Statement>      |
  1307.                   <Repeat Statement>     |
  1308.                   <For Statement>        |
  1309.                   <Case Statement>       |
  1310.                   <With Statement>       |
  1311.                   <Compound Statement>   |
  1312.                   <Assignment Statement> |
  1313.                   <Procedure Call>       |
  1314.                   <Return Statement>     |
  1315.                   <Goto Statement>
  1316.  
  1317. (Es gibt keine allgemeine Übersetzung für Statement; Anweisung kommt dem ei-
  1318.  gentlichen Namen aber schon recht nahe (wobei Statements aber auch Befehle
  1319.  u.ä. sein können. Alle oben aufgeführten Statements werden aber im Folgenden
  1320.  erklärt. - Anm.d.Ü.)
  1321.  
  1322.  
  1323. 9.1 IF-Anweisung
  1324. ----------------
  1325.  
  1326. (deutsch: wenn ... dann ...)
  1327.  
  1328. Die IF-Anweisung erlaubt das Testen verschiedener Alternativen. Es hat die
  1329. folgende Form:
  1330.  
  1331. <If Statement> ::= if <Boolean Expr> then <Statement> |
  1332.                    if <Boolean Expr> then <Statement>
  1333.                                      else <Statement>
  1334.  
  1335. Wenn der boolean Ausdruck TRUE ergibt, wird das Statement nach "then" ausge-
  1336. führt. Ergibt er aber FALSE, wird das Statement nach "else" ausgeführt, so-
  1337. fern eines existiert.
  1338.  
  1339. Hier gibt´s eine Mehrdeutigkeit. Seht Euch einmal das folgende Fragment an:
  1340.  
  1341.         if Expr then if Expr then Statement1 else Statement2
  1342.  
  1343. Zu welchem "if" gehört nun das "else"? - PCQ nimmt hier (wie die meisten Im-
  1344. plementationen) - das letztere "if".
  1345.  
  1346. (Sollen mehrere Anweisungen nach einem "then" abhängig vom "if"-Resultat aus-
  1347.  geführt werden, so muß nach dem "then" ein "begin" und am Ende des in Abhän-
  1348.  gigkeit auszuführenden Teils ein "end" stehen. Das ist auch bei anderen An-
  1349.  weisungen, wie WHILE (s.u.) möglich - Anm.d.Ü.)
  1350.  
  1351.  
  1352. 9.2 WHILE-Anweisung
  1353. -------------------
  1354.  
  1355. (deutsch: solange wie ... mache ...)
  1356.  
  1357. WHILE ist eine von mehreren Anweisungen, die Programmschleifen erlauben (die-
  1358. se Programmschleifen können abhängig von der Bedingung mehrfach durchlaufen
  1359. werden - Anm.d.Ü.).
  1360. Diese Anweisung hat folgende Form:
  1361.  
  1362. <While Statement> ::= while <Boolean Expr> do <Statement>
  1363.  
  1364. Beim Beginn der Schleife wird der boolean Ausdruck berechnet.
  1365. Falls das Ergebnis TRUE ist, wird der Teil des Statements ausgeführt. Ist das
  1366. abgeschlossen, wird der Ausdruck neu berechnet. Dieser Vorgang wird solange
  1367. durchgeführt, bis der Ausdruck FALSE ergibt. Sobald das passiert, wird nach
  1368. der WHILE-Schleife fortgefahren.
  1369.  
  1370. ("while <Boolean Expr> do begin <Statement> <Statement> ... end" funktioniert
  1371.  auch hier - Anm.d.Ü.)
  1372.  
  1373.  
  1374. 9.3 REPEAT-Anweisung
  1375. --------------------
  1376.  
  1377. (deutsch: wiederhole ...; bis ...)
  1378.  
  1379. Die "Repeat"-Schleife bietet eine leicht unterschiedliche Variante d. Schlei-
  1380. fen. Es hat die folgende Form:
  1381.  
  1382. <Repeat Statement> ::= repeat <Statements> until <Boolean Expr>
  1383.  
  1384. <Statements> ::= <Statement> | <Statement> ; <Statements>
  1385.  
  1386. Die nach der "Repeat"-Anweisung folgenden Anweisungen werden beim 1. Schlei-
  1387. fendurchlauf immer ausgeführt. Erst danach wird der boolean Ausdruck berech-
  1388. net. Ergibt der Ausdruck FALSE, wird der Anweisungen-Block nochmals durchlau-
  1389. fen. Ergibt er TRUE, wird mit dem Statement nach "until" fortgefahren.
  1390.  
  1391. (begin/end sind auch bei mehreren Statements NICHT nötig - Anm.d.Ü.)
  1392.  
  1393.  
  1394. 9.4 FOR-Anweisung
  1395. -----------------
  1396.  
  1397. (deutsch: von ... bis ... mache ...)
  1398.  
  1399. Die FOR-Anweisung stellt eine 3. Art von Schleifen dar. Sie ist für Zwecke
  1400. geeignet, in denen man genau weiß, wie oft die Schleife durchlaufen werden
  1401. soll. Der Syntax ist der folgende:
  1402.  
  1403. (Direction = Richtung (aufwärts oder rückwärts zählen) - Anm.d.Ü.)
  1404.  
  1405. <For Statement> ::= for <Variable Reference> :=
  1406.                         <Expression> <Direction>
  1407.                         <Expression> do <Statement>
  1408. <Direction> ::= to | downto
  1409.  
  1410. Das unterscheidet sich von PCQ V1.1. Bei einer "for"-Schleife wir der 1. Aus-
  1411. druck (der Anfangswert) berechnet und in der Referenz-Variablen (die im Index
  1412. aufgerufen wird) gespeichert. Dann wird der Index verglichen mit dem 2. Aus-
  1413. druck (dem Zielwert). Falls die Richtung "to" (aufwärts) und der Index klei-
  1414. ner oder gleich dem Zielwert ist, wird der Statement-Teil ausgeführt. Danach
  1415. wird der Index um 1 erhöht und erneut mit dem Zielwert verglichen. Das geht
  1416. dann solange weiter, bis der Index größer als der Zielwert ist. Ist das der
  1417. Fall, wird nach der "next"-Anweisung fortgesetzt.
  1418.  
  1419. Ist die Richtung "downto", passiert im Prinzip dasselbe, abgesehen davon, daß
  1420. der Index bei jedem Durchlauf um 1 verringert wird. Die Schleife wird dann
  1421. solange durchlaufen, bis der Index kleiner als der Zielwert ist.
  1422.  
  1423. Beachtet, daß die "for"-Schleife möglicherweise nicht ausgeführt wird, wenn
  1424. der Anfangswert größer als der Zielwert ist (für "to"-Loops oder im umgekehr-
  1425. ten Fall bei "downto"-Schleifen).
  1426.  
  1427. Beachtet außerdem, daß der Zielwert bei jedem Schleifendurchlauf vollkommen
  1428. neu berechnet wird. Wenn es also ein komplexer Ausdruck ist, solltet Ihr ihn
  1429. wohl besser vor der "for"-Anweisung in einer Variable zwischenspeichern.
  1430.  
  1431. Ihr könnt immer eine "While"- oder "Repeat"-Schleife anstatt einer "For"-
  1432. Schleife benutzen. Tatsächlich wird die "For"-Schleife auch am wenigsten be-
  1433. nutzt.
  1434.  
  1435.  
  1436. 9.5 CASE-Anweisung
  1437. ------------------
  1438.  
  1439. (deutsch: falls ... aus ... (dann) ...)
  1440.  
  1441. Die CASE-Anweisung wird dazu benutzt, einen Wert aus verschiedenen möglichen
  1442. Alternativen zu testen, und die Anweisungen in Abhängigkeit zum Ergebnis aus-
  1443. zuführen. Folgender Syntax:
  1444.  
  1445. (case vals = mögliche Werte - Anm.d.Ü.)
  1446.  
  1447. <Case Statement> ::= case <Expression> of <Alternatives> end |
  1448.                      case <Expression> of <Alternatives>
  1449.                                        else <Statement> end
  1450.  
  1451. <Alternatives> ::= <Alternative> | <Alternative> ; <Alternatives>
  1452.  
  1453. <Alternative> ::= <Case Vals> : <Statement>
  1454.  
  1455. <Case Vals> ::= <Case Val> | <Case Val> , <Case Vals>
  1456.  
  1457. <Case Val>  ::= <Const Expr> | <Const Expr> .. <Const Expr>
  1458.  
  1459. Bei der Ausführung der "case"-Anweisung wird der Ausdruck berechnet. Er wird
  1460. dann mit allen Fällen verglichen. Sobald ein Fall erfüllt ist, wird das fol-
  1461. gende Statement ausgeführt. Ist keiner der angegebenen Fällen eingetreten,
  1462. wird das Statement nach "else" ausgeführt, sofern eines existiert. Falls
  1463. nicht, wird mit dem Statement nach der "Case"-Schleife fortgefahren.
  1464.  
  1465. Beachtet, daß der Ausdruck nur 1 Mal berechnet wird, wodurch eine CASE-Anwei-
  1466. sung effizienter wie eine Serie aus IF-Anweisungen sein kann.
  1467.  
  1468. ("case ... of ... : begin ... end" ist möglich, um mehr als 1 Anweisung aus-
  1469.  führen zu lassen - Anm.d.Ü.)
  1470.  
  1471.  
  1472. 9.6 WITH-Anweisung
  1473. ------------------
  1474.  
  1475. Die WITH-Anweisung erlaubt das Spezifizieren einer Record-Variable, auf die
  1476. sich ein Statement bezieht. Innerhalb des Statements kann man Referenzen auf
  1477. die Felder des Records abkürzen, indem man nur den Feldnamen angibt. Das
  1478. spart etwas Tipparbeit und der Compiler generiert etwas effizienteren Code.
  1479. Nun zum Syntax:
  1480.  
  1481. <With Statement> ::= with <Expressions> do <Statement>
  1482.  
  1483. <Expressions> ::= <Expression> | <Expression> , <Expressions>
  1484.  
  1485. Wenn Ihr mehr als 1 Record (getrennt von Kommas) angebt, behandelt der Compi-
  1486. ler diese wie in Statements genistet, mit dem 1. Record im äußersten Bereich
  1487. und dem letzten im innersten.
  1488.  
  1489. Im Statement werden alle Referenzen zu Feldern als sich auf den innersten Re-
  1490. cord beziehend angenommen. Mehrdeutigkeiten können durch die Benutzung von
  1491. Spezifikationen des gesamten Records geklärt werden.
  1492.  
  1493. WITH-Anweisungen sind speziell dazu nützlich, wenn ein Referenz-Record lang
  1494. ist - er wird nur 1 Mal ausgeführt, was die Effizient erhöht. Sie ist auch
  1495. dann speziell nützlich, wenn es darum geht, Werte in einem Record zu platzie-
  1496. ren. Sie verbessert zwar nicht immer die Effizienz des Programms, spart aber
  1497. viel Tipparbeit.
  1498.  
  1499. Wenn Ihr ein Statement der Form "with ^p do ..." habt, ist es wahrscheinlich
  1500. ein Fehler, den Wert von p zu ändern. Z.B. ist es ein Fehler, den Speicher
  1501. für den Record einer "With"-Anweisung freizugeben. Dieser Fehler wird vom PCQ
  1502. zwar nicht entdeckt, es wäre aber gut, ihn zu vermeiden.
  1503.  
  1504.  
  1505. 9.7 COMPOUND-Anweisung
  1506. ----------------------
  1507.  
  1508. Die COMPOUND-Anweisung erlaubt die Benutzung einer Reihe von Statements in
  1509. jeder Situation, in der zumindest 1 Statement (davon) aufgerufen wird. Der
  1510. Syntax ist der Folgende:
  1511.  
  1512. <Compound Statement> ::= begin <Statements> end
  1513.  
  1514. Ein "Compound"-Statement kann überall dort benutzt werden, wo ein Statement
  1515. erlaubt ist und der Statement selbst generiert keinen Extra-Programmcode.
  1516.  
  1517.  
  1518. 9.8 ASSIGNMENT-Anweisung
  1519. ------------------------
  1520.  
  1521. Assignment-Anweisungen werden dazu benutzt, um den Wert von Variablen zu set-
  1522. zen. Sie haben die folgende Form:
  1523.  
  1524. <Assignment Statement> ::= <Variable Reference> := <Expression>
  1525.  
  1526. Beachtet, daß der Typ der Variable mit dem Typ des Ausdrucks übereinstimmen
  1527. muß (siehe "Typendeklarationen" für spezielle Regeln)
  1528.  
  1529.  
  1530. 9.9 PROCEDURE-Aufrufe
  1531. ---------------------
  1532.  
  1533. Prozedur-Aufrufe transferieren die Ausführung zu einer vorher definierten
  1534. Routine und übergeben die benötigten Parameter.
  1535. Dabei gilt der folgende Syntax:
  1536.  
  1537. (Procedure Call = Prozeduraufruf, Actual Params = übergebene Parameter,
  1538.  Expression = Ausdruck - Anm.d.Ü.)
  1539.  
  1540. <Procedure Call> ::= <Identifier> |
  1541.                      <Identifier> ( <Actual Params> )
  1542.  
  1543. <Actual Params> ::= <Actual Param> |
  1544.                     <Actual Param> ; <Actual Params>
  1545.  
  1546. <Actual Param> ::= <Expression>
  1547.  
  1548. Prozeduren unterscheiden sich dadurch von Funktionen, daß Funktionen einen
  1549. Wert zurückgeben und nur von Ausdrücken aufgerufen werden können, während
  1550. Prozeduren keinen Wert zurückgeben und nur von Statements aufgerufen werden
  1551. können.
  1552.  
  1553. Wenn eine Prozedur ausgeführt wird, wird jeder übergebene Parameter berechnet
  1554. und in den Stack geschrieben (von links nach rechts - im Gegensatz zu C!).
  1555.  
  1556.  
  1557. 9.10 RETURN-Befehl
  1558. ------------------
  1559.  
  1560. Normalerweise wird eine Prozedur bis zum Ende abgearbeitet und anschließend
  1561. mit dem Befehl nach dem Prozedur-Aufruf fortgefahren. Der "Return"-Befehl er-
  1562. laubt das sofortige Verlassen der aktuellen Prozedur. Er hat folgende einfa-
  1563. che Form:
  1564.  
  1565.     <Return Statement> ::= return
  1566.  
  1567. Der "Return"-Befehl ist nur innerhalb von Prozeduren erlaubt. Er darf nicht
  1568. innerhalb von Funktionen verwendet werden, da diese einen Wert zurückgeben
  1569. müssen. Der analoge Befehl in einer Funktion ist ein Assignment auf den Iden-
  1570. tifier der Funktion. Der "Return"-Befehl ist auch nicht im Hauptprogramm zu-
  1571. lässig, weil das Programm somit abbrechen würde. Diesen Zweck erfüllt der
  1572. "Exit"-Befehl.
  1573.  
  1574.  
  1575. 9.11 GOTO-Anweisung
  1576. -------------------
  1577.  
  1578. Nach der GOTO-Anweisung wird mit der Ausführung nach der angegebenen Sprung-
  1579. marke fortgefahren. Dies sollte man mit extremer Vorsicht verwenden und, wenn
  1580. möglich, vermeiden. Hier die Form:
  1581.  
  1582. <Goto Statement> ::= goto <Identifier>
  1583.  
  1584. Standard-Pascal erwartet, daß eine Goto-Sprungmarke aus einer Ziffern-Folge
  1585. besteht, und Turbo Pascal erweitert diese Definition, indem es auch Identi-
  1586. fier in Sprungmarken (Labels) erlaubt. PCQ-Pascal hingegen macht schon den
  1587. nächsten logischen Schritt, indem es Identifier als Sprungmarken erwartet -
  1588. und keine Nummern!
  1589.  
  1590. Die meisten Programmierer sind der Ansicht, daß das Arbeiten mit GOTO einfach
  1591. nur schlechte Programmierung ist, weil es das Verstehen und Debuggen von Pro-
  1592. grammen erschwert. Es gibt jedoch auch andere Probleme. Wenn man z.B. "goto"
  1593. innerhalb einer "for"-Schleife nach außen verwendet, wird der Stack des Pro-
  1594. gramms durcheinandergebracht. Ähnliche Sachen passieren bei der "With"-Anwei-
  1595. sung, ganz zu schweigen davon, was passiert, wenn man vom außerhalb in eine
  1596. "for"-Schleife springt...
  1597.  
  1598. Die Moral der Geschichte ist: versucht sie zu vermeiden!
  1599.  
  1600.  
  1601.  
  1602. 10. Ein- und Ausgabe
  1603. ^^^^^^^^^^^^^^^^^^^^
  1604.  
  1605. Es gibt einige Routinen im PCQ, die die Ein- und Ausgabe betreffen. Sie die-
  1606. nen als Interface mit AmigaDOS-Routinen. Die Pascal-Ein/Ausgabe-Routinen be-
  1607. nutzen alle AmigaDOS zum Lesen und Schreiben.
  1608.  
  1609. Pascal-Ein/Ausgabe hat jedoch verschiedene Vorteile. Zunächst einmal werden
  1610. alle PCQ-Files gepuffert, d.h. daß nicht jedes Mal zum Lesen/Schreiben auf
  1611. AmigaDOS zurückgegriffen werden muß. Das erhöht die Geschwindigkeit etwas.
  1612.  
  1613. Der andere Vorteil ist die Benutzung der Pascal-Routinen Read, ReadLn, Write
  1614. und Writeln.
  1615.  
  1616. Wenn man ein File im Programm entweder als "File of Some Type" (File eines
  1617. bestimmten Typs) oder als "Text" deklarieren, allocatet man im Endeffekt ei-
  1618. nen Record.
  1619. Benutzt man also so etwas wie "var filevar : file of integer", erzeugt man in
  1620. Wirklichkeit soetwas wie einen Record, der so aussehen würde (wenn seine Fel-
  1621. der direkt ansprechbar wären):
  1622.  
  1623.    file = record
  1624.         HANDLE  : Ein AmigaDOS File-Handle
  1625.         NEXT    : Ein Zeiger auf das nächste offene Pascal-File
  1626.         BUFFER  : die Adresse des Filepuffers
  1627.         CURRENT : die Stelle des Puffers des nächsten Read/Write
  1628.         LAST    : die letzte Position eines Read
  1629.         MAX     : die Adresse des Puffer-Endes +1
  1630.         RECSIZE : die Größe der File-Elemente
  1631.         INTERACTIVE : ein boolean Wert - TRUE heißt, daß das File ans CLI ge-
  1632.                       bunden ist
  1633.         EOF     : ein boolean Wert
  1634.         ACCESS  : entweder MODE_NEWFILE oder MODE_OLDFILE
  1635.    end;
  1636.  
  1637.  
  1638. 10.1 Text- und Typen-Files
  1639. --------------------------
  1640.  
  1641. Pascal hat 2 verschiedene Filetypen. Der normale Filetyp wird "typed File"
  1642. genannt und wird in folgender Weise deklatiert:
  1643.  
  1644.                   FileVar : File of ElementType
  1645.  
  1646. Typed Files sind im Grunde genommen unbegrenzte Sequenzen von Elementen von
  1647. diesem einen Element-Typ. Der Write-Befehl kann benutzt werden, um individu-
  1648. elle Elemente ans Ende des Files zu schreiben, und der Read-Befehl dazu, um
  1649. das aktuelle Element einzulesen und den File-Zeiger zum nächsten Element zu
  1650. bewegen. Ihr könnt nur einen Elementtyp in jedes "typed File" schreiben.
  1651.  
  1652. Typed Files speichern Ihre Elemente in genau demselben Format, wie sie auch
  1653. im Speicher auftreten, wodurch sie oft unlesbar sind. Ein File von Zeichen-
  1654. elementen ist zwar lesbar, aber ein File von Integer-Elementen würde unver-
  1655. ständlich sein. Da "typed Files" immer komplette Elemente speichern, hat je-
  1656. des Element notwendigerweise eine feste Größe.
  1657.  
  1658. Ihr braucht also eigentlich nichts anderes als "typed Files" - alles was Ihr
  1659. mit Pascal machen könnt, könnt Ihr damit machen. Wegen der Bequemlichkeit un-
  1660. terstützt Pascal auch den Textfile-Typ. Das Textfile ist ein spezieller Typ
  1661. vom "File of Char", aber nicht kompatibel damit! Textfiles bestehen aus ASC-
  1662. II-Zeichen, die in Zeilen von variabler Länge unterteilt sind. Jede Zeile
  1663. wird durch ein spezielles "Neue Zeile-Zeichen" beendet, der am Amiga das Li-
  1664. neFeed-Zeichen ist (ASCII-Code 10).
  1665.  
  1666. Da Textfiles (wie diese Anleitung und alle Sourcefiles) so gleich sind, ent-
  1667. hält Pascal viele verschiedene eingebaute Routinen zum Lesen und Schreiben
  1668. in und aus diesen. Die meisten der Standardtypen haben beispielsweise eine
  1669. spezielle Routine um diese in ASCII-Zeichen zu konvertieren und diese in ein
  1670. File zu schreiben. Diese Routinen werden automatisch vom Compiler aufgerufen,
  1671. um jeden Wert in einer Write-Prozedur in ein Textfile zu schreiben. Ähnliche
  1672. Routinen existieren zum Lesen derselben Typen. Die Beschreibungen der Lese-
  1673. und Schreibprozeduren weiter unten beschreiben genau, wie diese Conversion
  1674. funktioniert.
  1675.  
  1676. Es gibt auch eine spezielle Form der Read- und Write-Prozeduren, die speziell
  1677. für die Arbeit mit Textfiles gemacht wurden - die ReadLn- und WriteLn-Befeh-
  1678. le. Auch sie werden weiter unten beschrieben; beachtet aber, daß diese Rou-
  1679. tinen ausschließlich für Textfiles geeignet sind, da "typed Files" keine Zei-
  1680. len haben!
  1681.  
  1682.  
  1683. 10.2 Öffnen von Files
  1684. ---------------------
  1685.  
  1686. Es gibt verschiedene eng verwandte Routinen zum Öffnen von Pascal-Files. Zum
  1687. Öffnen von Input-Files (existierende Files die zum Lesen geöffnet werden)
  1688. kann man die ReOpen()-Funktion oder die Reset()-Prozedur verwenden.
  1689. Sie werden wie folgt definiert:
  1690.                Reset(var FileVar : File or Text;
  1691.                         FileName : String;
  1692.                       BufferSize : Integer);
  1693. Die "Reset"-Prozedur öffnet ein File zum Lesen. Der FileVar-Parameter spezi-
  1694. fiziert die Pascal-Filevariable, die mit dem AmigaDOS-File assoziiert ist.
  1695. Der Filename muß auch den Pfad enthalten, sofern notwendig. Dieser kann jeder
  1696. vom AmigaDOS akzeptierte Filename sein, wodurch sich dieser auch auf den
  1697. Drucker, einem Console-Fenster oder ähnlichem beziehen kann.
  1698.  
  1699. Der Buffersize-Parameter (Puffergröße) spezifiziert die Buffergröße in Bytes.
  1700. Wenn PCQ versucht, das File zu öffnen, versucht es diesen Speicher als Puffer
  1701. zu reservieren. Falls das nicht möglich ist, setzt es IOResult und bricht ab.
  1702. Der BufferSize-Parameter ist komplett optional. Ist er nicht angegeben, wird
  1703. der voreingestellte Wert von 128 verwendet.
  1704.  
  1705. Wenn Ihr die automatische IO-Überprüfung benutzt, bricht das Programm mit ei-
  1706. nem Runtime-Error ab, wenn das File nicht geöffnet werden kann. Wenn Ihr das
  1707. Ganze manuell überprüft, wird lediglich IOResult gesetzt.
  1708.  
  1709. Die Variable FileVar sollte sich nicht auf ein File beziehen, das schon offen
  1710. ist. Entweder sollte das File zuerst geschlossen werden oder eine andere Fi-
  1711. levariable verwendet werden.
  1712.              ReOpen(fname      : String;
  1713.                     var fvar   : file or text;
  1714.                     buffersize : Integer) : Boolean
  1715. ReOpen ist die Funktion-Form von Reset. Es versucht das File auf die selbe
  1716. Weise wie Reset zu öffnen, und falls alles ok ging, gibt es True zurück.
  1717. Gab es irgendein Problem, ist das Ergebnis False.
  1718.  
  1719. ReOpen setzt niemals IOResult, wenn Ihr also automatisches IO-Überprüfen be-
  1720. nutzt, bricht ReOpen nie das Programm ab. Wie in der Reset-Prozedur ist auch
  1721. hier der BufferSize-Parameter optional.
  1722.  
  1723. Wenn Ihr aber ein File zum Schreiben öffnen wollt (wobei jedes existierende
  1724. File desselben Namen gelöscht wird!), könnt Ihr die Rewrite-Prozedur oder die
  1725. Open()-Funktion benutzen.
  1726. Sie werden wie folgt definiert:
  1727.              Rewrite(var FileVar : File or Text;
  1728.                         FileName : String;
  1729.                       BufferSize : Integer);
  1730. Rewrite öffnet ein AmigaDOS-File zum Schreiben und löscht dabei ein evtl.
  1731. existierendes File desselben Namens. Die Parameter sind identisch zu denen
  1732. des Reset-Befehls und die BufferSize ist immer noch optional.
  1733.  
  1734. ReWrite setzt IOResult. Das Verhalten von Rewrite ist hier identisch zu dem
  1735. von Reset.
  1736.  
  1737. Wie bei allen File-Öffnen-Routinen sollte man keine Filevariable verwenden,
  1738. die schon zu einem offenen File gehört.
  1739.       function open(filename : string;
  1740.                     filevar  : file of ..., oder Text;
  1741.                     BufferSize : Integer): Boolean;
  1742. Öffnet ein File für den Schreibzugriff. Sollte ein File gleichen Namens
  1743. bereits existieren, dann wird es durch diesen Befehl automatisch gelöscht.
  1744. Ist alles OK, wird True zurückgegeben, ansonsten False.
  1745. Denkt daran, daß das Öffnen eines existierenden Files zum Schreiben den In-
  1746. halt dieses Files löscht.
  1747.  
  1748. Open setzt IOResult nicht und der BufferSize-Parameter ist optional...
  1749.  
  1750.  
  1751. 10.3 Schreiben in Files
  1752. -----------------------
  1753.  
  1754. Die Ausgabe in Pascal wird durch die Write- und Writeln-Prozeduren durchge-
  1755. führt. Anders als die meisten Pascal-Prozeduren, akzeptieren diese Routinen
  1756. eine unbegrenzte Anzahl an Parametern. Wenn Ihr in ein Textfile schreibt,
  1757. können die Parameter viele verschiedene Typen haben. Die Write-Prozedur hat
  1758. die folgende Basis-Form:
  1759.      Write(var FileVar : Text or Typed File, Expressions...)
  1760. FileVar ist optional. Falls nicht angegeben, wird der Standard-Textfile-Out-
  1761. put an dessen Stelle gesetzt. Wenn die Filevariable ein "typed File" ist,
  1762. muß jeder Ausdruck vom Elementtyp sein. Sie werden in das File ohne Lücken
  1763. dazwischen geschrieben, formatiert wie sie auch im Speicher stehen.
  1764.  
  1765. Das Schreiben in ein Textfile ist eine komplett andere Geschichte. Zunächst
  1766. einmal kann jeder Ausdruck die Form "e:m:n" haben, wobei e der Ausdruck (Ex-
  1767. pression) ist sowie m und n Integerkonstanten. m spezifiziert die minimale
  1768. Feldgröße - falls das Item, das geschrieben werden soll kürzer als m Zeichen
  1769. groß ist, werden Leerstellen in das Feld geschrieben. n ist nur erlaubt, wenn
  1770. e real (reell) ist; es spezifiziert wie viele Zeichen rechts des Dezimal-
  1771. punkts geschrieben werden sollen. Die voreingestellten Werte für m und n sind
  1772. 1 und 2. Was geschrieben wird hängt vom Typ ab, wie folgt:
  1773.  
  1774. Integer
  1775. Short
  1776. Byte    Diese 3 Typen werden alle als ASCII-Ziffern-Sequenzen geschrieben.
  1777.         Ihnen werden keine Leerstellen voran- oder nachgestellt, wobei bei
  1778.         Short- und Integer-Werten ein Minus vorangestellt sein kann.
  1779.  
  1780. Real    Der Ganzzahlteil (vor dem Dezimalpunkt) wird normal ausgegeben. Falls
  1781.         n ungleich 0 ist, wird ein Dezimalpunkt gefolgt von n Nachkommastel-
  1782.         len ausgegeben. Beachtet, daß bei reellen Zahlen m die Anzahl der
  1783.         Ziffern links vom Dezimalpunkt angibt, nicht die volle Feldgröße (was
  1784.         möglicherweise in der nächsten Version geändert wird).
  1785.  
  1786. Char    Ein Zeichen wird genau als ein Zeichen ausgegeben, unverändert.
  1787.  
  1788. Array of Char
  1789.         Das gesamte Feld wird Zeichen für Zeichen ausgegeben.
  1790.  
  1791. String  Die gesamte Zeichenkette wird bis zum abschließenden NULL-Zeichen
  1792.         ausgeben (wobei das NULL-Zeichen nicht ausgegeben wird).
  1793.  
  1794. Boolean Es wird entweder das Wort TRUE oder FALSE geschrieben, ohne anführen-
  1795.         de oder abschließende Leerstellen.
  1796.  
  1797.            WriteLn(var FileVar : Text; Expressions...)
  1798.  
  1799. Wie "Write", nur mit anschliessendem LineFeed. Kann nur bei Textfiles ver-
  1800. wendet werden.
  1801.  
  1802.  
  1803. 10.4 Lesen aus Files
  1804. --------------------
  1805.  
  1806. Das Einlesen in Pascal wird von der Read-Prozedur durchgeführt. Wie bei den
  1807. Write-Prozeduren akzeptiert Read jede Anzahl von Parametern und viele Typen
  1808. der Parameter, wenn man von einem Textfile liest. Dabei gilt das folgende
  1809. Format:
  1810.    Read(var FVar : Text or Typed File; Variable References....)
  1811. Der FVar-Parameter ist optional. Falls dieser fehlt, wird das Standard-Input-
  1812. Textfile verwendet.
  1813.  
  1814. Wenn sich FVar auf ein "typed File" bezieht, wird jede Referenz-Variable mit
  1815. den subsequenten File-Elementen gefüllt bis das EOF (Ende des Files) erreicht
  1816. wird oder irgendein Fehler auftritt. Das Einlesen eines Textfiles ist eine
  1817. etwas flexiblere Arbeit. Wie bei der Write-Anweisung, hängt auch hier das,
  1818. was passiert, vom gelesenen Typ ab, wie folgt:
  1819.  
  1820. Integer
  1821. Short
  1822. Byte    Überspringt alle Leerzeichen und Tabs (alle Zeichen mit ASCII-Code
  1823.         kleiner oder gleich 32). Ist das erste Zeichen mit einerm ASCII-Code
  1824.         größer als 32 keine Ziffer oder ist das File-Ende erreicht, wird ein
  1825.         IO-Error ausgegeben (siehe "Exit-Prozeduren").
  1826.         Falls nicht, werden die Ziffern bis zur ersten Nicht-Ziffer eingele-
  1827.         sen. Die sich ergebende Nummer wird zurückgegeben und er Filepointer
  1828.         zeigt auf diese Nicht-Ziffer.
  1829.  
  1830. Real    Ein Integer wird genau wie oben beschrieben eingelesen. Ist das näch-
  1831.         ste Zeichen ein Punkt, werden die nächsten Ziffern wieder eingelesen
  1832.         (als Nachkommastellen) bis zur 1. Nicht-Ziffer. Ein Real-Wert benö-
  1833.         tigt weder einen Nachkommateil noch einen Dezimalpunkt.
  1834.  
  1835. Char    Liest das nächste einzelne Zeichen.
  1836.  
  1837. Array of char
  1838.         Liest solange Zeichen in das Datenfeld, bis das Datenfeld voll ist
  1839.         oder ein EOL gefunden wird. Sollte vorher ein EOL gefunden werden,
  1840.         dann wird ab dieser Stell der Rest des Datenfeldes mit Leerzeichen
  1841.         aufgefüllt, wobei der Filepointer auf das EOL-Zeichen zeigt. Um das
  1842.         loszuwerden, muß Readln aufgerufen werden.
  1843.  
  1844. String  Liest Zeichen ein, bis ein EOL gefunden wird. Das EOL steht immer am
  1845.         linken Ende des Datenflusses und wird dann automatisch durch ein
  1846.         Null-Byte ersetzt. Der Filepointer bleibt beim EOL-Zeichen stehen.
  1847.         Beachtet, daß diese Routine keine Längenüberprüfung durchführt. Ihr
  1848.         müßt also sicherstellen, daß auch alle Zeichen des Strings eingelesen
  1849.         werden können.
  1850.  
  1851. Boolean Nicht möglich.
  1852.  
  1853. Eine Reihe von Referenzvariablen in einer Read-Prozedur verhält sich genauso
  1854. wie jede andere der Referenzen in individuellen Read-Prozeduren. Somit ist
  1855.  
  1856.                     Read(Input, Var1, Var2);
  1857.  
  1858. identisch zu
  1859.  
  1860.                     Read(Input, Var1); Read(Input, Var2);
  1861.  
  1862. das genauso identisch ist zu
  1863.  
  1864.                     Read(Var1); Read(Var2);
  1865.  
  1866.          ReadLn(var FVar : Text; Variable References...)
  1867. Readln ist identisch zu Read, mit der Ausnahme, daß nachdem alle spezifizier-
  1868. ten Variablen eingelesen wurden, dieser Befehl Zeichen bis zum nächsten EOL
  1869. frißt (incl. dem EOL). Dieser Befehl kann nur in Textfiles verwendet werden.
  1870.  
  1871.  
  1872. 10.5 File-Puffer
  1873. ----------------
  1874.  
  1875. Wie Standard-Pascal (aber im Gegensatz zu Turbo Pascal), erlaubt PCQ auf den
  1876. File-Puffer direkt zuzugreifen. Die Syntax der Referenz sieht wie folgt aus:
  1877.  
  1878.                    <File Variable Reference> ^
  1879.                           e.g. FileVar^
  1880.  
  1881. Dieser Ausdruck hat denselben Typ als die Elemente des Files selbst (Textfi-
  1882. les haben Char-Elemente). Bei Input-Files zeigt dieser Syntax nach dem näch-
  1883. sten Element, der durch die Read()-Prozedur eingelesen wird. Wenn EOF(File-
  1884. Var) TRUE ist, dann ist FileVar^ ungültig.
  1885.  
  1886. Bei Output-Files zeigt die File-Puffer-Referenz immer auf den Output-Puffer.
  1887. Das ist nicht der Wert, der mit der Write()-Prozedur ausgegeben wird - siehe
  1888. die Beschreibung von Put() weiter unten.
  1889.  
  1890. Logischerweise ist der Filepuffer, auf den Ihr mittels diesem Syntax zu-
  1891. greift, nur 1 Element lang, aber der eigentliche Puffer im Speicher kann be-
  1892. liebig groß sein. Siehe die File-Öffnen-Befehle für Informationen über das
  1893. Setzen der Puffergröße.
  1894.  
  1895. Wenn Ihr den Filepuffer benutzt, werdet Ihr wahrscheinlich einen oder beide
  1896. der folgenden Routinen benutzen:
  1897.               Get(var FileVar : Text or Typed File)
  1898. Get bewegt lediglich den Filezeiger vom aktuellen Element zum nächsten. Das
  1899. kann DOS dazu veranlassen, den Buffer neu zu füllen, aber normalerweise ist
  1900. das bloß dazu gedacht, ein Feld in der Filevariable selbst anzupassen. Es ist
  1901. ein Fehler, diese Routine bei einem File aufzurufen, für das EOF(FileVar)
  1902. TRUE ist.
  1903.  
  1904. Jedes Lesen von einem "typed File" der Form "Read(FVar,Element)" kann wie
  1905. folgt umgesetzt werden:
  1906.  
  1907.         Element := FVar^; { To assign the current value }
  1908.         Get(FVar);        { To advance the file pointer }
  1909.               Put(var FileVar : Text or Typed File)
  1910. Put bewegt den Filezeiger hinter das aktuelle Element in einem Output-File
  1911. und schreibt den Puffer auf die Disk, wenn nötig. Jedes Statement der Form
  1912. "Write(FVar,Expr)", wobei FVar ein "typed File" ist, kann wie folgt umgesetzt
  1913. werden:
  1914.  
  1915.         FVar^ := Expr; { Set the buffer value }
  1916.         Put(FVar);     { Commit the buffer    }
  1917.  
  1918. Beachtet, daß solange bis die Put-Prozedur aufgerufen wird, alle Assignments
  1919. in den Filepuffer sich gegenseitig überschreiben.
  1920.  
  1921.  
  1922. 10.6 Ein- und Ausgabe-Überprüfung (IO-Checken)
  1923. ----------------------------------------------
  1924.  
  1925. Die Ein- & Ausgabe kann wohl mehr unvorhergesehene Fehler verursachen als je-
  1926. der andere Programmierbereich. PCQ-Pascal fängt IO-Fehler in einer von 2 We-
  1927. gen ab. Der erste nennt sich automat. IO-Checken - PCQ überprüft dabei nach
  1928. jedem IO-Vorgang auf Fehler. Ist dabei ein Fehler aufgetreten, bricht das
  1929. Programm mit einem Runtime-Error ab. Das ist die voreingestellte Methode!
  1930.  
  1931. Wenn Ihr das automatische Überprüfen mittels der {$I-} Compilerdirektive ab-
  1932. schaltet, müßt Ihr selbst auf Fehler überprüfen. Das geschieht, indem man die
  1933. IOResult-Funktion aufruft, die 0 zurückgibt, sofern alles gut gegangen ist.
  1934. Jede andere Zahl bedeutet, daß ein Fehler aufgetreten ist. Wenn Ihr IOResult
  1935. aufruft, löscht Ihr automatisch dessen Wert. Wenn Ihr also den Fehlercode ir-
  1936. gendwo später noch benutzen wollt, müßt Ihr diesen in einer Variable spei-
  1937. chern.
  1938.  
  1939. IOResult wird durch jede IO-Routine gesetzt. Alle IO-Routinen funktionieren
  1940. nicht, wenn IOResult nicht gleich 0 ist. Ihr solltet also so oft wie möglich
  1941. nach Fehlern prüfen, um das Überspringen von READs und WRITEs zu vermeiden.
  1942.  
  1943. Die Werte, die von IOResult zurückgegeben werden, sind dieselben wie die Run-
  1944. time-Fehler - mögliche Werte sind in der Sektion "Exit-Prozeduren" beschrie-
  1945. ben.
  1946.  
  1947.  
  1948. 10.7 Standard Ein & Ausgabe
  1949. ---------------------------
  1950.  
  1951. Eine der trickreichen Teile der Amiga-Programmierung ist, daß ein Programm
  1952. von 2 verschiedenen Umgebungen gelauncht werden kann. Das CLI ruft ein Pro-
  1953. gramm ähnlich wie MS-DOS auf - das Programm hat klare Input- und Output-Kanä-
  1954. le. Die Workbench auf der anderen Seite bietet nichts dergleichen. Ein Pro-
  1955. gramm, das Input- und Output-Kanäle benötigt, muß diese selbst anlegen.
  1956.  
  1957. Alle PCQ-Programme richten eine Art von Standard-Input- und -Output-Kanäle
  1958. ein, auf die durch die Textfiles Input und Output zugegriffen werden kann.
  1959. Was diese Files repräsentieren hängt natürlich von der Umgebung ab, von der
  1960. das Programm aufgerufen wurde.
  1961.  
  1962. Nehmen wir erstmal einen einfachen Fall. Wenn Ihr ein Programm vom CLI star-
  1963. tet, wirken Input und Output auf das CLI-Fenster. Wenn Ihr Ausgabe-Umleitung
  1964. verwendet, wirken Input und Output auf die Kanäle, die in der Kommandozeile
  1965. angegeben sind (siehe auch das AmigaDOS-Handbuch).
  1966.  
  1967. Wenn das Programm von der Workbench gestartet wurde, durchläuft der Startup-
  1968. Code verschiedene Schritte, um Input und Output einzurichten. Zuallererst
  1969. wird der Wert der Standard-String-Typed-Konstante StdInName untersucht. Ist
  1970. dieser Nil, wird kein File geöffnet und im Bezug auf Input entstehen große
  1971. Probleme. Wenn nicht, versucht der Startup-Code das File zu öffnen. Ist das
  1972. nicht möglich, bricht es mit dem Run-Time Error 53 ab. Wenn alles gut gegan-
  1973. gen ist, ist der Input eingerichtet.
  1974.  
  1975. Als nächstes untersucht der Startup-Code den StdOutName. Ist dieser Nil, wird
  1976. der Output nicht eingerichtet, wodurch alle Write-Prozeduren ein spezielles
  1977. File benutzen sollten. Zeigt StdOutName auf denselben String wie StdInName
  1978. (nicht 2 Strings mit denselben Inhalten - es muß auf dieselbe Speicherstelle
  1979. zeigen), dann wird Output mit demselben Filehandle wie Input verbunden. Die
  1980. voreingestellten Werte für StdInName und StdOutName haben diese Möglichkeit.
  1981. Wenn einer davon fehlschlägt, versucht der Startup-Code, ein File gemäß Std-
  1982. OutName zu öffnen; funktioniert das, wird der Output abhängig davon zugewie-
  1983. sen. Ansonsten bricht das Programm mit dem Runtime-Error 57 ab.
  1984.  
  1985. Die voreingestellten Werte für die beiden Kanäle sind in der PCQ.lib wie
  1986. folgt definiert:
  1987.  
  1988.         CONST
  1989.             StdInName  : String = "CON:0/0/640/200/";
  1990.             StdOutName : String = StdInName;
  1991.  
  1992. Abhängig zu den oben spezifizierten Regeln, resultiert das normalerweise in
  1993. einem Full-Screen-Console-Fenster, das geöffnet wird, mit Input daraus und
  1994. Output dahin.
  1995.  
  1996. Beachtet, daß StdInName und StdOutName als Typen-Konstanten definiert sind.
  1997. Sie können keine Variablen sein, weil sie vor dem gesamten Programmcode aus-
  1998. geführt werden. Ist das ein größeres Problem, könnt Ihr beide als Nil defi-
  1999. nieren und innerhalb Eures Programmes Input und Output als irgendwas belie-
  2000. biges öffnen. Ihr solltet besser Input und Output nur dann nochmals benutzen,
  2001. wenn Euer Programm von der Workbench gestartet wurde (Ihr könnt das überprü-
  2002. fen, indem Ihr GetStartupMsg aus "Utils/Parameters.i" aufruft).
  2003.  
  2004. Wenn Ihr Euer Programm mit dem "-s" klein-initializierten Code-Schalter kom-
  2005. piliert habt, ist all das aus: Input und Output werden nicht eingerichtet,
  2006. und auch keine der anderen IO-Routinen wird initialisiert. Siehe auch "Small
  2007. Initialization Code".
  2008.  
  2009.  
  2010.  
  2011. 11. Zeichenkettenvariablen (Strings)
  2012. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  2013.  
  2014. PCQ-Pascal hat Strings ähnlich zu denen von C, und absolut nicht ähnlich zu
  2015. Turbo Pascal. Das ist natürlich nicht so gut, da man TurboPascal-Strings viel
  2016. einfacher arbeiten kann.
  2017.  
  2018. Strings können als '^char'- Typen angesehen werden. Somit belegen alle String-
  2019. Variablen genau 4 Bytes. Diese enthalten die Adresse des eigentlichen Textes.
  2020. Der Text kann beliebig lang sein. Er wird mit dem Zeichen Chr(0) beendet.
  2021. Ein Statement wie:
  2022.  
  2023.         StringVar := "A String"
  2024.  
  2025. beinhaltet die Adresse des konstanten Strings in der Stringvariable, eher als
  2026. dies in den String selbst in irgendeine existierende Lücke zu kopieren.
  2027.  
  2028. Im Programmtext wird jeder String mit doppelten Anführungszeichen einge-
  2029. grenzt, anstelle der einfachen, wie sie in "char"-Datenfeldern zu finden
  2030. sind. Also:
  2031.  
  2032.         "Ein String"   ist wirklich ein String, während
  2033.         'Kein String'  ein array [1..11] of char ist
  2034.  
  2035. Strings sind als einfache Zeiger definiert, wodurch "StringVar^" korrekt ist.
  2036. Dieser ist vom Typ Char. Er zeigt auf das erste Byte im Stringpuffer. Aber
  2037. im Gegensatz zu normalen Zeigern können die einzelnen Zeichen eines Strings
  2038. ebenfalls durch eine Subscript-Notation erreicht werden. Um beispielsweise
  2039. das 4. Zeichen eines Strings zu bekommen, könnte man "StringVar[3]" benutzen
  2040. (StringVar[0] ist das 1. Element!).
  2041.  
  2042.  
  2043. 11.1 Reservieren von String-Speicher
  2044. ------------------------------------
  2045.  
  2046. Da die eigentlichen String-Variablen nur eine Adresse beinhalten, muß ein be-
  2047. stimmter Speicher für den eigentlichen Text reserviert werden. In PCQ-Pascal
  2048. muß man den Speicher ausdrücklich vom System reservieren oder die Adresse ei-
  2049. ner Puffer-Variablen auf den String assignen. Dazu gibt´s verschiedene Funk-
  2050. tionen, die alle im Include-File "StringLib.i" definiert sind, um Speicher
  2051. für Strings zu reservieren. Diese sind:
  2052.                AllocString(Size : Integer) : String
  2053. AllocString gibt einfach einen uninitialisierten Speicherbereich der Mindest-
  2054. größe "Size" Bytes an. Dieser Speicher wird als PCQ-Speicher behandelt, wo-
  2055. durch es nach der Benutzung ans System zurückgegeben wird (siehe "Speicher-
  2056. verwaltung").
  2057.                 strdup(InString : String) : String
  2058. Die strdup-Funktion (String-Verdoppelung) entspricht dem folgenden:
  2059.  
  2060.                 temp := AllocString(strlen(InString));
  2061.                 strcpy(temp,InString);
  2062.                 strdup := temp;
  2063.  
  2064. Es wird somit genügend Speicher reserviert, um den Input-String darin zu hal-
  2065. ten. Danach wird eine Kopie des Input-Strings in den neuen Puffer gemacht.
  2066. Dieser Speicher wird auch als PCQ-Speicher betrachtet (mit allen daraus re-
  2067. sultierenden Konsequenzen).
  2068.  
  2069. Die andere Möglichkeit, einen String-Puffer einzurichten, ist, die Sting-Va-
  2070. riable auf die Adresse eines irgendwo deklarierten Arrays zu assignen.
  2071.  
  2072.         Var
  2073.             String1 : String;
  2074.             Buffer1 : Array [0..127] of Char;
  2075.         begin
  2076.             String1 := Adr(Buffer1);
  2077.  
  2078. Dadurch wird ein 128 Zeichen großer Puffer für String1 eingerichtet. Versucht
  2079. Ihr aber, einen 129 Zeichen großen String in diesem Puffer zu speichern, tre-
  2080. ten alle Arten von Problemen auf - seid also vorsichtig!
  2081.  
  2082.  
  2083. 11.2 Benutzung von Escape-Zeichen
  2084. ---------------------------------
  2085.  
  2086. Eine weitere interessante Tatsache bei der Stringbehandlung ist die Möglich-
  2087. keit, ESC(APE)-Sequenzen einzubauen. Das ist vor allem dazu nützlich, Zei-
  2088. chen, die nicht so einfach in ein Programm-Sourcefile geschrieben werden kön-
  2089. nen, doch benutzen zu können. Sobald Sie einen Backslash (\) in irgendeinen
  2090. Text (Char, Array of Char oder String) schreiben, wird das unmittelbar fol-
  2091. gende Zeichen besonders bearbeitet.
  2092.  
  2093. Bis jetzt werden folgende Escape-Sequenzen von PCQ unterstützt:
  2094.  
  2095. (chr heißt ASCII-Zeichen-Nummer - Anm.d.Ü.)
  2096.  
  2097.            \n   Line Feed, chr(10)
  2098.            \t   Tab, chr(9)
  2099.            \0   Null, chr(0)
  2100.            \b   Backspace, chr(8)
  2101.            \e   ESC, chr(27)
  2102.            \c   CSI (Control Sequence Introducer), chr($9B)
  2103.            \a   Attention, chr(7)
  2104.            \f   Form Feed, chr(12)
  2105.            \r   Carriage Return, chr(13)
  2106.            \v   Vertical Tab, chr(11)
  2107.  
  2108. Jedes andere Zeichenläuft ohne Umänderung durch den Compiler, sodaß auch fol-
  2109. gendes möglich ist:
  2110.  
  2111.            \\   ergibt einen einzelnen Backslash (\)
  2112.            \'   ergibt ein einzelnes Anführungszeichen
  2113.            \"   ergibt ein doppeltes Anführungszeichen
  2114.  
  2115. Somit wird ein String wie
  2116.  
  2117.       "A\tboy\nand\\his \"dog.\""
  2118.  
  2119. so ausgegeben:
  2120.  
  2121.       |A       boy
  2122.       |and\his "dog"
  2123.  
  2124. (wobei | den linken Rand repräsentiert)
  2125.  
  2126.  
  2127. 11.3 StringLib
  2128. --------------
  2129.  
  2130. StringLib.i ist eine Include-Datei im Utils-Verzeichnis, die ein paar Funk-
  2131. tionen in der Art von C für die Benutzung mit Strings beinhalten. Diese Funk-
  2132. tionen werden im Include-File selbst erklärt. Der Sourcecode für diese Rou-
  2133. tinen befindet sich im Sourcecode der runtime-library, die man auf Anfrage
  2134. beim Autor erhalten kann.
  2135.  
  2136.  
  2137.  
  2138. 12. Speicher-Verwaltung
  2139. ^^^^^^^^^^^^^^^^^^^^^^^
  2140.  
  2141. Eine der Probleme bei der Amiga-Programmierung ist, daß es kein Resource-
  2142. Tracking gibt. In einem MS-DOS-Programm kann man wie verrückt Files öffnen
  2143. und Speicher reservieren und dann das Programm bloß schließen und alles ist
  2144. ok. Auf dem Amiga würden alle Files geöffnet und der Speicher reserviert
  2145. bleiben. Man muß also "selbst aufräumen".
  2146.  
  2147. Um Euch dabei zu helfen, benutzt PCQ-Pascal ein spezielles Speicherreservie-
  2148. rungsschema, das die Intuition-AllocRemember-Routine benutzt, um die Spur
  2149. jeder Speicherreservierung zu behalten. Bricht das Programm ab, wird jeder
  2150. Speicher, der nicht freigegeben wurde, automatisch von einer Exit-Prozedur
  2151. freigegeben.
  2152.  
  2153. Das funktioniert aber nur bei Speicher, die durch einer der speziellen PCQ-
  2154. Routinen New, AllocString (von Utils/StringLib.i) oder GetMem (von Utils/PCQ-
  2155. Memory.i) reserviert wurde. Dieser Speicher wird dann PCQ-Speicher genannt,
  2156. er unterscheidet sich aber in keinerlei Hinsicht vom normalen Systemspeicher,
  2157. abgesehen davon, daß er zurückgegeben wird.
  2158.  
  2159. Obwohl er automatisch freigegeben wird, sollte man den Speicher sobald wie
  2160. möglich wieder freigeben - er könnte von anderen Programmen gebraucht werden.
  2161. Um PCQ-Speicher freizugeben benötigt man Dispose, FreeString oder FreePCQMem.
  2162. Macht Ihr das nicht, wird der Speicher zwar ans System zurückgegeben, aber
  2163. die PCQ-Speicherroutinen merken davon nichts. Sie versuchen daher, diese er-
  2164. neut zu reservieren, wenn das Programm abbricht -> Guru.
  2165.  
  2166. PCQ-Speicher wird immer mit den Flags MEMF_PUBLIC und MEMF_CLEAR reserviert.
  2167. Wenn Ihr Chip-Memory benötigt, solltet Ihr die normale Exec-Funktion AllocMem
  2168. (aus Exec/Memory.i) benutzen.
  2169.  
  2170.  
  2171. 12.1 HeapError (Überlauf-Fehler)
  2172. --------------------------------
  2173.  
  2174. Was passiert nun, wenn die Speicherroutinen vom PCQ keinen Speicher reservie-
  2175. ren können, die ein User verlangt? - Das hängt vom Wert von HeapError ab, ei-
  2176. ner Standard-Address-Variable. HeapError beinhaltet die Adresse einer Funk-
  2177. tion, die einen Header der folgenden Form hat:
  2178.            Function HeapFunc(Size : Integer) : Integer;
  2179. Der Size-Parameter ist die Speichermenge, die der Reservierer zu bekommen
  2180. versucht hat, und der zurückgegebene Integerwert bestimmt, wie der Reservie-
  2181. rer auf das Problem antwortet. Wird 0 zurückgegeben, bricht der Reservierer
  2182. mit dem Runtime-Error 54 ab. Bei 1, gibt der Reservierer Nil zurück, wodurch
  2183. man nach jedem New, AllocString oder GetMem auf einen Nil-Wert prüfen muß.
  2184. Gibt HeapError 2 zurück, versucht der Reservierer dieselbe Reservierung noch-
  2185. mals. Das gibt Euch die Möglichkeit, etwas Speicher freizugeben, wenn mög-
  2186. lich. Schlägt das nochmals fehl, wird HeapError nochmals aufgerufen.
  2187.  
  2188. Um eine Funktion wie HeapError zu installieren, muß man etwas verwenden wie:
  2189.  
  2190.                      HeapError := @HeapFunc;
  2191.  
  2192. ... wobei HeapFunc wie oben definiert ist.
  2193.  
  2194.  
  2195.  
  2196. 13. Exit-Prozeduren
  2197. ^^^^^^^^^^^^^^^^^^^
  2198.  
  2199. Exit-Prozeduren sind Routinen, die nachdem das Hauptprogramm fehlgeschlagen
  2200. ist, durchlaufen werden sollen (oder falls ein Runtime-Error aufgetreten
  2201. ist). Sie werden dazu benutzt, um Resourcen ans System zurückzugeben, oder
  2202. um nett abzubrechen, oder sogar um Runtime-Errors rückgängig zu machen.
  2203.  
  2204. Das funktioniert so: Bricht ein Programm ab - warum auch immer - untersucht
  2205. PCQ den Wert von ExitProc, einer Standard-Address-Variable. Ist sie nicht
  2206. Nil, setzt PCQ ExitProc auf Nil und ruft die Prozedur auf, auf die er vorher
  2207. gezeigt hat. Ist die Prozedur abgelaufen, überprüft PCQ nochmals ExitProc und
  2208. ruft weiter Exit-Prozeduren auf bis ExitProc Nil ist. Der normale PCQ-Initia-
  2209. lisierungs-Code richtet eine Exit-Prozedur ein, die den gesamten Speicher,
  2210. der durch New oder AllocString reserviert wurde, wieder freigibt, und außer-
  2211. dem alle offenen Pascal-Files schließt. Normale Programme haben somit minde-
  2212. stens eine Exit-Prozedur.
  2213.  
  2214. Um aus einer Prozedur eine Exit-Prozedur zu machen, muß man zuerst eine Rou-
  2215. tine ohne Parameter definieren. Danach muß die ExitProc-Standard-Variable auf
  2216. die Adresse der Routine gesetzt werden. In den meisten Fällen werdet Ihr wohl
  2217. den letzten Wert von ExitProc speichern wollen, wodurch alle anderen Exit-
  2218. Prozeduren auch laufen können. Innerhalb der Exit-Prozedur selbst, solltet
  2219. Ihr ExitProc auf den vorherigen Wert zurücksetzen.
  2220.  
  2221. Es gibt 2 zusätzliche Variablen, die mit Exit-Prozeduren zusammenhängen und
  2222. die nur innerhalb der Prozedur wahr ist, wenn sie als Exit-Prozedur aufgeru-
  2223. fen wurde. Sie existieren immer, aber Ihr Wert wird nur gesetzt, wenn das
  2224. Programm abbricht. Diese sind:
  2225.  
  2226. ExitCode    ExitCode beinhaltet den Wert jedes Runtime-Errors, der das Ab-
  2227.             brechen des Programms verursacht hat. Dies ist entweder ein Wert,
  2228.             den Ihr durch die Exit()-Routine übergeben habt, oder ein Run-
  2229.             time-Errorcode.
  2230.  
  2231. ExitAddr    ExitAddr ist die Addresse, bei der ein Runtime-Error aufgetreten
  2232.             ist. Dies ist nur wahr, wenn ExitCode nicht null ist. Er kann
  2233.             (theoretisch) dazu benutzt werden, um von einer Routine zurück-
  2234.             zukehren, aber Ihr müßt Euch dann schon ziemlich gut mit dem ei-
  2235.             gentlichen Runtime-Code auskennen, um das zum Laufen zu bekommen.
  2236.  
  2237.  
  2238.  
  2239. 14. Laufzeitfehler (Runtime-Errors)
  2240. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  2241.  
  2242. Einige Dinge verursachen Lauzeitfehler. Passiert das, wird ExitCode auf einen
  2243. speziellen Wert gesetzt, der schließlich an AmigaDOS zurückgegeben. AmigaDOS
  2244. hingegen ignoriert das normalerweise, wodurch Ihr das normalerweise niemals
  2245. zu Gesicht bekommen werdet. Die beiden einzigen Wege, um den Rückgabewert zu
  2246. erhalten, sind das Programm in einem Script laufenzulassen, oder es mit dem
  2247. Run-Befehl von AmigaDOS laufen zu lassen. In beiden Fällen gibt AmigaDOS
  2248. "ProgramName failed returncode #" aus, sofern der Wert ungleich 0 ist.
  2249.  
  2250. Folgende Runtime-Errors werden von PCQ-Programmen erzeugt:
  2251.  
  2252.         Code  Beschreibung
  2253.       ----------------------------------------------
  2254.         50  kein Speicher für IO-Puffer (1)
  2255.         51  Read nach EOF (1)
  2256.         52  Input-File ist nicht geöffnet (2)
  2257.         53  StdInName konnte nicht geöffnet werden (3)
  2258.         54  New() ist fehlgeschlagen (4)
  2259.         55  Integer durch 0 geteilt
  2260.         56  Output-File nicht geöffnet (2)
  2261.         57  StdOutName konnte nicht geöffnet werden (3)
  2262.         58  EOF vor dem 1. Zeichen gefunden beim Einlesen eines Integers (1)
  2263.         59  keine Zeichen gefunden beim Einlesen eines Integer (1)
  2264.         60  Reichweiten-Fehler
  2265.  
  2266. Die folgenden AmigaDOS-Fehlercodes können durch einen Aufruf von Open,
  2267. ReOpen, Write, Read, usw. entstehen: (1)
  2268.  
  2269.        103  freier Speicherplatz reicht nicht as
  2270.        202  Objekt wird gerade benutzt
  2271.        203  Objekt existiert bereits
  2272.        204  Verzeichnis nicht gefunden
  2273.        205  Objekt nicht gefunden
  2274.        206  Fehlerhafte Fenster-Spezifikation
  2275.        210  Fehlerhafter Komponenten-Name
  2276.        212  Objekt vom falschen Typ
  2277.        213  Diskette nicht validiert
  2278.        214  Diskette schreibgeschützt
  2279.        218  Device nicht gemountet
  2280.        221  Diskette voll
  2281.        223  File schreibgeschützt
  2282.        224  File lesegeschützt
  2283.        226  keine Disk im Laufwerk
  2284.  
  2285. (1) Diese Fehler verursachen nur Laufzeitfehler, wenn automatisches IO-Error-
  2286.     Überprüfen eingeschaltet ist (voreingestellt). Habt Ihr die {$I-} Direk-
  2287.     tive verwendet, um das IOResult selbst zu überprüfen, bricht das Programm
  2288.     nicht automatisch ab.
  2289. (2) PCQ kann nicht immer abbrechen, wenn das File nicht offen ist. Wenn es
  2290.     kann, wird dieser Fehler verursacht. Wenn nicht, gibt´s einen Systemab-
  2291.     sturz!
  2292. (3) Diese Fehler treten im Initialisierungscode auf bevor irgendwelche Exit-
  2293.     Prozeduren aufgerufen werden.
  2294. (4) Siehe Sektion "Speicherverwaltung".
  2295. (5) Tritt nur bei Range-Checking-ON auf (mittels der {$R+} Direktive ein-
  2296.     schaltbar)
  2297.  
  2298.  
  2299.  
  2300. 15. Compiler-Direktiven
  2301. ^^^^^^^^^^^^^^^^^^^^^^^
  2302.  
  2303. Es gibt diverse Optionen, die PCQ unterstützt, die aber nicht für alle Pro-
  2304. gramme nützlich sind. Zum Beispiel sollte eine große Applikation keinen Run-
  2305. time-Error verursachen, wenn es ein File nicht öffen kann. Daher erlaubt PCQ-
  2306. Pascal verschiedene Aspekte des von Eurem Code generierten Programm vorzube-
  2307. stimmen.
  2308.  
  2309. Diese Optionen werden durch Compiler-Direktiven kontrolliert. Diese sind in
  2310. Kommentaren enthalten, und müssen mit dem Dollarzeichen "$" als 1. Zeichen
  2311. im Kommentar beginnen. Direkt danach muß ein Zeichen folgen, daß die Direk-
  2312. tive näher bestimmt, die dann wieder von keinem oder mehreren Zeichen für
  2313. zusätzliche Informationen gefolgt wird.
  2314.  
  2315. Ein Komma kann zum Trennen verschiedener Direktiven benutzt werden, das sieht
  2316. dann so aus (schaltet IO-Cheken aus und Range-Checken an):
  2317.  
  2318.     {$O-,R+}
  2319.  
  2320. Die folgenden Direktiven werden unterstützt:
  2321.              {$A Any number of assembly instructions}
  2322. Dieses Kommando bindet Assembler-Instruktionen mit in das assemblierte File
  2323. ein.
  2324.  
  2325.                           {$B+} or {$B-}
  2326. Die $B Direktive schaltet Kurzschluß-Berechnungen (short-circuit evaluations)
  2327. an/aus. Benutzt Ihr $B+, um die Kurzschluß-Berechnungen anzuschalten, was
  2328. voreingestellt ist, dann berechnet PCQ boolean Ausdrücke normal. Sobald aber
  2329. das Endergebnis des Ausdrucks bekannst ist, wird der Rest des Ausdrucks über-
  2330. sprungen. D.h. z.B. in einer Reihe von AND-Fällen wird, sobald ein Fall FALSE
  2331. ergibt, der Rest des Arguments nicht berechnet. In einer Reihe von OR-Fällen
  2332. wird, sobald ein Fall TRUE ergibt, der Rest des Arguments ebenfalls nicht be-
  2333. rechnet. Der Ausdruck wird bei Kurzschluß-Berechnung wird der Ausdruck immer
  2334. von links nach rechts berechnet.
  2335. Die Kurzschluß-Berechnung macht die Boolean-Berechnung etwas schneller, vor
  2336. allem in langen Gleichungen.
  2337. Schaltet Ihr die Kurschluß-Berechnungen mittels der $B- Direktive aus, wird
  2338. der gesamte boolean Ausdruck berechnet, auch wenn das, was herauskommt, zwei-
  2339. fellos feststeht. Der Ausdruck wird nicht unbedingt von links nach rechts be-
  2340. rechnet.
  2341.  
  2342.                             {$I "fname"}
  2343. Dadurch wird das File "fname" als Eingaberoutine an der aktuellen Fileposi-
  2344. tion mit eingebunden. Nach der Einbindung wird mit dem Originalfile fortge-
  2345. fahren. Nach dieser Direktiven können keine anderen Direktiven mehr (in der
  2346. selben Klammer) stehen.
  2347. Um das mehrmalige Einlesen desselben Files zu verhindern, merkt sich der Com-
  2348. piler eine Liste aller Files, die bereits eingelesen wurden, und liest bei
  2349. nochmaliger Einlese-Aufforderung das File nicht mehr ein. Beachtet, daß nur
  2350. der eigentliche Filename, nicht aber der Verzeichnispfad, verglichen wird.
  2351. Somit sollten alle Include-Files verschiedene Namen haben!
  2352. Fast alle Beispielprogramme demonstieren die Benutzung der Includefiles.
  2353.  
  2354.                           {$I+} or {$I-}
  2355. Die andere Art der $I Direktive bestimmt das Verhalten Eurer Programme nach
  2356. Ein/Ausgabefehlern (IO-Errors). Das voreingestellte Verhalten, das mit dem
  2357. der {$I+} Direktiven übereinstimmt, ist, einen Laufzeitfehler zu verursachen,
  2358. sobald ein Fehler in einer IO-Routine erkannt wird. Mit der anderen Option,
  2359. die mit der {$I-} Direktiven einschaltbar ist, erwartet das Programm die
  2360. Überprüfung der IOResult-Funktion nach IO-Operationen und die davon abhängige
  2361. Behandlung der Fehler. Siehe "Ein und Ausgabe".
  2362.  
  2363.                  {$SN} oder {$SX} oder {$SP} oder {$SD}
  2364. Die $S Option kontroliert das Speichern (mit Speichern ist hier das Zwischen-
  2365. speichern im Arbeitsspeicher gemeint - Anm.d.Ü.) von globalen Variablen und
  2366. Typenkonstanten.
  2367.  
  2368. Die N-Option (Normale Speicherung) sagt dem Compiler, daß er für alle folgen-
  2369. den globalen Variablen Speicher im Datensegment reservieren soll, und auch
  2370. eine externe Definition für den Identifier ausgeben soll (XDEF in Assembler),
  2371. der von externen Routinen benutzt werden kann. Das ist das normale Speicher-
  2372. schema für PCQ-Programme.
  2373.  
  2374. Die X-Option (eXterne Speicherung) sagt dem Compiler, daß alle folgenden Va-
  2375. riablen außerhalb des Programms definiert werden. Daher sollte der Compiler
  2376. keinen Speicher für die Variablen reservieren, sondern nur eine externe Re-
  2377. ference erzeugen soll (XREF in Assembler). Das ist das normale Speicherschema
  2378. für externe Files.
  2379.  
  2380. Die P-Option (Private Speicherung) sagt dem Compiler, daß er Speicher für
  2381. globale Variablen reservieren soll, aber den Identifier nicht selbst expor-
  2382. tieren. Das dient dazu, externen Files globale Variablen zu erlauben, die
  2383. keine Auswirkung auf das Hauptprogramm haben.
  2384.  
  2385. Die D-Option (vorDefinierte Speicherung) setzt die Speicherung auf den Stan-
  2386. dard-Wert zurück. In einem externen File wirkt das wie {$SX} und in einem
  2387. normalen Programm wie {$SN}.
  2388.  
  2389.                           {$O+} or {$O-}
  2390. Diese Optionen entsprechen den {$I+} und {$I-} Optionen.
  2391.  
  2392.                           {$R+} or {$R-}
  2393. Die $R Direktive bestimmt, ob der Compiler überprüfen soll, ob Indexwerte in-
  2394. nerhalb der Arrayweite liegt. Das voreingestellte Verhalten ist {$R-}, d.h.
  2395. daß der Compiler den Extra-Code nicht generiert. Spezifiziert man {$R+}, er-
  2396. zeugt der Compiler dann (wenn ein Indexwert außerhalb eines Arrays liegt -
  2397. Anm.d.Ü.) einen Runtime-Error 60. Dies erweitert und verlangsamt den Code
  2398. natürlich beträchtlich, weshalb dies nur in der Testphase eines Programmes
  2399. durchgeführt werden sollte.
  2400.  
  2401.  
  2402.  
  2403. 16. Typen-Konvertierungen
  2404. ^^^^^^^^^^^^^^^^^^^^^^^^^
  2405.  
  2406. In einer stark typisierten Sprache wie Pascal muß es einen Weg geben, um die
  2407. Typenregeln zu umgehen. Dabei benutzt PCQ dieselben Methode wie TurboPascal
  2408. und Modula-2. Der Format für eine Type-Cast (Konvertierung) ist wiefolgt:
  2409.  
  2410.         <Type ID> ( <Expression or Variable Reference> )
  2411.  
  2412. Das sieht nur wie eine Funktion aus, ist aber keine. Ein Type-Cast generiert
  2413. keinen Code - sie läßt nur Code durch den Compiler kommen. Das kann aller-
  2414. dings zu ernsthaften Problemen führen. Ein Type-Cast wie "Short(Enumerate-
  2415. Var)" verursacht Probleme, weil aufgezählte Variablen normalerweise 1 Byte
  2416. lang sind, während Ihr dem Compiler mitgeteilt habt, es als 2 Byte-Wert an-
  2417. zunehmen, wobei das andere Byte dann undefiniert ist. Der korrekte Weg um
  2418. das zu schaffen wäre die Benutzung der Ord()-Funktion gewesen, oder es zumin-
  2419. dest stattdessen in 1 Byte zu konvertieren.
  2420.  
  2421. Der Unterschied zwischen Short() und Ord() in diesem Beispiel ist, daß Ord()
  2422. eine Typentransferfunktion ist, während Short() absolut keine Funktion ist.
  2423. Hier wäre da noch ein 2. Beispiel:
  2424.  
  2425.         Writeln(Integer(2.0));
  2426.         Writeln(Trunc(2.0));
  2427.  
  2428. Diese beiden Zeilen schreiben nicht dieselben Werte. Trunc(), eine andere
  2429. Typentransferfunktion, konvertiert den reellen Wert 2.0 in den Integer-Wert
  2430. 2, bevor dieser geschrieben wird. Die Integer-"Funktion" macht garnichts,
  2431. wodurch das Programm lediglich den reellen Wert ausgibt, als ob dieser ein
  2432. Integer-Wert wäre, was was sicherlich eine absurde Zahl produziert.
  2433.  
  2434. Generell sollte ein Ausdruck nicht in einen größeren Ausdruck konvertiert
  2435. werden, und das Konvertieren eines einfachen Ausdrucks (eine Ordnungs- oder
  2436. reelle Zahl bzw. ein Zeiger-Wert) in einen komplexen Typ (ein Array oder eine
  2437. Record-Referenz) oder ungekehrt wird fast immer Nonsens-Ergebnisse liefern.
  2438.  
  2439.  
  2440.  
  2441. 17. Kurzer Anfangscode (Small Initialisation Code)
  2442. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  2443.  
  2444. Wenn Ihr ein Programm erzeugen wollt, das nicht den Kopf eines normalen PCQ-
  2445. Programms hat, ist diese Option recht nützlich. Wenn Ihr beispielsweise keine
  2446. Pascalfiles benutzt, benötigt Ihr den gesamten Code von Writeln() nicht. Wenn
  2447. Ihr also den Startup- und Schlußcode, den PCQ minimal an Euer Programm an-
  2448. fügt, kürzen wollt, könnt Ihr die "-s" Option (für small = kurz) in der Kom-
  2449. mandozeile angeben. Wenn Ihr z.B. Tiny.p mit dem kurzen Anfangscode kompilie-
  2450. ren wolltet, müßtet Ihr folgende Zeile eingeben:
  2451.         Pascal Tiny.p Tiny.asm -s
  2452. Der Programmkopf, den Ihr dabei meidet, ist jedoch nicht unnötig groß, und
  2453. eines der Probleme, die Ihr ohne diesen habt, ist, daß Ihr ihn nicht benutzen
  2454. könnt. Außerdem könnt Ihr, wenn Ihr die "-s" Option in der Kommandozeile be-
  2455. nutzt, keine Pascal-IO-Routinen benutzen. Diese sind:
  2456.         Write, WriteLn, Read, ReadLn, Get,
  2457.         Put, Open, ReOpen, Close, IOResult
  2458. Der Compiler übergeht Referenzen an alle diese Identifier, ausgenommen von
  2459. IOResult. Beachtet aber, daß der Kompiler niemals Referenzen in separat kom-
  2460. pilierten Files (externen Files) oder in Objektcode-Libraries sehen wird.
  2461. Die Moral der Geschichte ist, daß Ihr extrem vorsichtig mit dieser Option
  2462. sein solltet, wenn Ihr keinen Systemabsturz erzeugen wollt...
  2463.  
  2464. Was fehlt also genau? - Der normale Startup-Code macht das folgende:
  2465.  
  2466.     1. Datenaustausch mit der Kommandozeile oder Workbench-Mitteilung
  2467.     2. öffnet die Intuition.-, Dos.- und MathFFP.library
  2468.     3. richtet die Ein- und Ausgabe ein und öffnet ein Fenster, wenn nötig
  2469.     4. initialisiert die Speicherreservierungsliste und die OpenFile-Liste,
  2470.        um diese beim Verlassen des Programms freigeben zu können
  2471.     5. richtet eine Exitprozedur ein, die Speicher und Files wieder freigibt
  2472.  
  2473. Wie Ihr seht, sind darunter ein paar zieml. große Routinen: Open(), Close(),
  2474. die Exit-Prozedur usw. Die Kurze-Anfangscode-Routine macht daher folgendes:
  2475.  
  2476.     1. Datenaustausch mit der Kommandozeile oder Workbench-Mitteilung
  2477.     2. öffnet die Intuition.-, Dos.- und MathFFP.library
  2478.     3. initialisiert die Speicherliste und richtet eine einfache Routine zur
  2479.        Freigabe alles New()-Speichers ein
  2480.  
  2481. Und das wär´s dann auch schon. Nach den Ergebnissen des Autors belegt das
  2482. Kompilat vom Programm "Program Test; begin end." normalerweise rund 2,5 KB,
  2483. während es weniger als 700 Bytes belegt, wenn der Kurze Anfangscode verwendet
  2484. wird.
  2485.  
  2486.  
  2487.  
  2488. 18. Externe Files
  2489. ^^^^^^^^^^^^^^^^^
  2490.  
  2491. Bei der Entwicklung des Compilers stellte sich heraus, daß das Schreiben ei-
  2492. nes ganzen Programms in nur 1 Sourcefile unhandlich ist, so waren z.B. die
  2493. Kompilierzeiten wahnsinnig lang. Um die Sachen etwas aufzuteilen, wurde eine
  2494. Methode zur getrennten Kompilierung in der Art von TurboPascals Units ent-
  2495. wickelt (die allerdings nicht ganz so mächtig sind).
  2496. Es können Funktionen ähnlich wie in anderen Pascal-Compilern als
  2497. Extern deklariert werden:
  2498.  
  2499. Externe Files haben das folgende Format:
  2500.  
  2501.            <External File> ::= External; <Definitions>
  2502.  
  2503. In anderen Worten, beginnt ein externes File mit dem reservierten Wort "Ex-
  2504. ternal", gefolgt von einem Semikolon und einer beliebigen Anzahl von Defini-
  2505. tionsblocks, welche, wie oben definiert, Funktionen, Prozeduren, Variablen,
  2506. usw. sein können.
  2507.  
  2508. Immer wenn eine Prozedure oder Funktion definiert wird, exportiert PCQ-Pascal
  2509. die Identifier, wodurch sie von anderen Files benutzt werden können. Diese
  2510. anderen Files beziehen sich auf die Routine, indem eine externe Referenz in
  2511. Ihrem Code eingebunden wird (siehe "Externe Referenzen" in der "Prozeduren
  2512. und Funktionen" Sektion). Wenn Ihr also die Prozedur DoIt in Eurem externen
  2513. File definiert, würdet Ihr die folgende Deklaration in jedem anderen File an-
  2514. geben, in dem die Routine benutzt wird:
  2515.  
  2516.                         Procedure DoIt;
  2517.                             External;
  2518.  
  2519. Diese Deklaration teilt dem Compiler mit, daß er den Identifier von einem
  2520. anderen File importieren soll.
  2521.  
  2522. Die Definintion von globalen Variablen und Typen-Konstanten in einem externen
  2523. File ist etwas komplizierter. Um auf eine globale Variable Eures Hauptpro-
  2524. gramms in Eurem externen File zugreifen zu können, wird die Deklaration einer
  2525. globalen Variable in einem externen File als eine Variable, die aus einem an-
  2526. deren File importiert werden soll, angesehen. Globale Variablen können also
  2527. voreingestellterweise nur in normalen Programmfiles definiert werden. Die
  2528. Deklaration einer globalen Variable in einem externen File führt also zu kei-
  2529. ner Speicherreservierung! - Diese Voreinstellung kann jedoch mittels der $S
  2530. Direktiven verändert werden.
  2531.  
  2532. Wenn Ihr ein externes File benutzt habt, müßt Ihr sichergehen, daß seine Rou-
  2533. tinen im schließlich ausführbaren Programm eingebaut werden. Um dies zu tun,
  2534. muß der Filename im Linkerbefehl wie folgt eingebaut werden:
  2535.     Blink Haupt.o Extern1.o ... to HauptProgramm Library PCQ.lib
  2536. In anderen Worten heißt das, daß der Einbau jedes externen Objektfiles (die
  2537. Ausgabe des Assemblers) im Linkerbefehl nach dem Mainfile aber vor dem
  2538. Schlüsselwort erfolgen muß. Die Reihenfolge ist dabei egal.
  2539.  
  2540. Während Pascal eine case-insensitive (keine klein-groß-Unterscheidung) Spra-
  2541. che ist, ist Assembler nicht. Somit muß, wenn Ihr externe Referenzen benutzt,
  2542. die erste Referenz in Eurem Programm (entweder die Variablendeklaration oder
  2543. der eigentliche Kopf der Prozedur oder Funktion) dieselbe Schreibweise wie
  2544. die Definition im externen File aufweisen. Weitere Benutzungen können eine
  2545. beliebige Schreibweise haben - lediglich die erste wird dazu benutzt, um die
  2546. Referenz zu erzeugen.
  2547.  
  2548.  
  2549.  
  2550. 19. Einige Anmerkungen für Assembler-Programmierer
  2551. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  2552.  
  2553. In früheren Versionen des Compilers waren die Register von d2 bis d7 sowie
  2554. a2 und a3 immer erreichbar. Außerdem waren die Scratch-Register auch zwischen
  2555. Statements erreichbar. Das stimmt nicht mehr, wodurch wohl einige Assembler-
  2556. routinen umgeschrieben werden müssen.
  2557.  
  2558. PCQ V1.2 benutzt die Register viel effizienter, d.h. daß alle Datenregister
  2559. benutzt werden können. PCQ reserviert Register von d7 abwärts, um Unteraus-
  2560. drucksergebnisse zu halten, wodurch die Wählbarkeit von Registern innerhalb
  2561. von Ausrücken vom Pascal-Code abhängt. Zwischen Statements sind alle Daten-
  2562. register einmal wieder wählbar.
  2563.  
  2564. Adreßregister werden wie vorher benutzt: a7 ist der Stack-Zeiger, a6 zeigt
  2565. auf die Library-Base, a5 der Stack-Frame-Zeiger und a4 der Zeiger auf vor-
  2566. herige Frames. Der Compiler kann a3 und a2 während Ausdrücken verwendet wer-
  2567. den, um zwischenzeitliche Adreßwerte zu halten.
  2568.  
  2569. Die Systemroutinen verwenden d0,d1,a0 und a1 als Scratch, bewahren aber alle
  2570. anderen Register.
  2571.  
  2572.  
  2573.  
  2574. 20. Fehlermeldungen
  2575. ^^^^^^^^^^^^^^^^^^^
  2576.  
  2577. Wenn der Compiler einen Fehler erkennt, gibt er die aktuelle und letzten Zei-
  2578. len vor dem Fehler aus, und hebt den Teil hervor, in deren Gegend der Fehler
  2579. aufgetreten ist. In der nächsten Zeile wird die Zeilennummer und die aktuelle
  2580. Prozedur oder Funktion sowie etwas (hoffentlich) beschreibender Text angege-
  2581. ben.
  2582.  
  2583. Der erste Error, den PCQ ausgibt, ist normalerweise ziemlich genau. Danach
  2584. werden aber auch Fehlermeldungen ausgeben, die überhaupt nicht existieren.
  2585. Dies sollte man am besten ignorieren. Der Compiler bricht daher nach 4 Feh-
  2586. lermeldungen ab.
  2587.  
  2588. Mit der "-q" quiet (ruhig) Befehlszeilenoption bekommen die Fehlermeldungen
  2589. eine regulärere Form, und zwar:
  2590.  
  2591. "source file name" At ##,## : Error Text
  2592.  
  2593. Dabei gibt das 1. ## die Zeile und das 2. ## die Spalte an. Das macht das
  2594. Programmieren automatischer Compilier-Routinen einfacher.
  2595.  
  2596. (Ein paar Hinweise zur Fehlersuche:
  2597.  - oft vergißt man einmal einen Strichpunkt am Ende eines Befehles (und er-
  2598.     hält dann eine ganze Reihe von Fehlermeldungen, obwohl der Rest des Pro-
  2599.     grammes richtig compiliert wird)
  2600.  - das hervorgehobene Zeichen kann auch ein Punkt sein (was dann nicht immer
  2601.    ohne weiteres erkennbar ist) - Anm.d.A.)
  2602.  
  2603.  
  2604.  
  2605. 21. Quellen
  2606. ^^^^^^^^^^^
  2607.  
  2608. Dieser Compiler wurde zu Lernzwecken geschrieben. Folgende Informationsquel-
  2609. len hat der Autor dabei benutzt:
  2610.  
  2611. Zunächst einmal wäre da das Amiga 1.3 "Native Developer´s Update", das ein
  2612. 4 Disks umfassendes Paket von Commodore (genauergesagt von CATS). Es enthält
  2613. die kompletten C- und Assembler-Include-Libraries, amiga.lib, ALink und alle
  2614. möglichen anderen Sachen. Wichtiger war vielleicht, daß auch die Amiga-Auto-
  2615. docs darin enthalten sind, ein Satz Dokumentationsfiles, die jede Funktion
  2616. der Standard-Amiga-Libraries und -Devices beschreibt. Mit 20$ (US) sind die-
  2617. se jedoch ziemlich billig. Die Adresse, bei der Ihr das Teil bekommen könnt,
  2618. ist:
  2619.         C.A.T.S
  2620.         1200 Wilson Drive
  2621.         West Chester, PA 19380
  2622.  
  2623. Außerdem benutzte der Autor die "Amiga ROM Kernel Manuals", die der offiziel-
  2624. le Buchsatz zur Amiga-Programmierung ist. Ohne diese wäre das Programmieren
  2625. wesentlich schwerer. Insbesondere das Intuition-Handbuch ist ziemlich wich-
  2626. tig. Auch sehr nützlich ist das Handbuch für Libraries und Devices. Diese
  2627. Bücher sind allerdings groß und sehr teuer... Manche behaupten auch, daß die-
  2628. se fehlerhaft und schwer zu verstehen sind; der Autor stellte aber fest, daß
  2629. sie doch relativ fehlerfrei und klar sind.
  2630.  
  2631. Als nächstes wäre Anders Bjerin´s C-Manual anzuführen. Es enthält eine Menge
  2632. über Intuition und Graphics. Außerdem sollte die C-Orientierung kein allzu
  2633. großes Problem darstellen. Es befindet sich übrigens auf den Fish-Disks 456
  2634. und 457 (entpackt erstreckt es sich auf 4 volle Disks!).
  2635.  
  2636. Folgende Quellen wurden vom Autor benutzt, um Informationen speziell über
  2637. Compiler zu bekommen:
  2638.  
  2639. 1. PDC ist ein frei kopierbarer C-Compiler von Jeff Lydiatt. Dies ist ein
  2640.     sehr gutes Programm, obwohl es in letzter Zeit von DICE, GCC und anderen
  2641.     wirklich guten C-Compilern überholt wurde. Der Autor lernte vieles von
  2642.     diesem Compiler und verwendete diesen auch häufig.
  2643. 2. Pascal-S ist eine kleine Demonstration eines Pascal-p-Code-Compilers der
  2644.     Elektro-Technischen-Hochschule Zürich. Der Sourcecode konnte ein paar
  2645.     Fragen beantworten, ist aber echt kein gutes Beispiel f. Programmierstil.
  2646. 3. Small-C ist ein weiterer frei kopierbarer C-Compiler, der zwar nicht sehr
  2647.     mächtig ist, aber die Einfachheit des Sourcecodes macht es zu einer sehr
  2648.     praktischen Referenz.
  2649. 4. Ein Buch mit dem Titel "Brinch Hansen on Pascal Compilers" von Per Brinch
  2650.     Hansen. Dieses Buch half dem Autor mehr, als alle anderen Bücher, die er
  2651.     zu diesem Thema gelesen hat, während er den Compiler geschrieben hat. Von
  2652.     diesem Buch bekam er vor allem gesagt, was er alles falsch gemacht hat...
  2653. 5. Die "Toy-Compiler" Serie im "Amiga-Transactor" von Chris Gray. Diese Serie
  2654.     ist sehr informativ, wobei Chris Gray, der Autor von Draco, hier das
  2655.     Prinzip des Compilerbaus erklärt.
  2656. 6. "Compiler: Principles, Techniques und Tools" von Aho, Sethi und Ullman.
  2657.     Dies ist das große Buch, das sogenannte "Dragon-Buch", das letzte Wort
  2658.     über das Compilerschreiben. Wenn Ihr etwas wissen wollt, ist´s schon
  2659.     drin, aber mit einem dezenten mathemat. Hintergrund wäre man besser dran!
  2660.     Obwohl das ein Textbuch für einen Kurs war, den der Autor gemacht hat,
  2661.     hat er niemals mehr als ein paar Seiten davon gelesen...
  2662.  
  2663. (der Draco-Compiler von Chris Gray befindet sich auf den Fish-Disks 76 & 77
  2664.  mit einem Update auf Fish 201, eine ältere Version des PDC-Compilers von
  2665.  Jeff Lydiatt befindet sich auf der Fish-Disk 110 - Anm.d.Ü.)
  2666.  
  2667.  
  2668.  
  2669. 22. Zukünftige Erweiterungen
  2670. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  2671.  
  2672. Der Autor benutzte V1.2 schon ein paar Monate vor der Veröffentlichung, wo-
  2673. durch er ziemlich sicher über seine Qualität ist. Es ist jedoch ein so großer
  2674. Unterschied seit der letzten Version, daß es eigentlich Probleme geben müßte.
  2675. Daher haben Fehler-Verbesserungen, wie immer, höchste Priorität.
  2676.  
  2677. Danach werden wohl optionale C-Calling-Conventions kommen, integriertes Peep-
  2678. hole-Optimieren und vielleicht IEEE-Single-Precesion-Reals.
  2679.  
  2680. Version 1.3 wird wohl eine Kompatibilitäts-Veröffentlichung sein. Darin ent-
  2681. halten sein werden Strings wie in Turbo, Funktionen, die Werte zurückgeben
  2682. können, double-precision-Reals und die Turbo-Typen Word, LongInt, ShortInt
  2683. usw. Aus Address wird wohl zu Pointer werden, Integer zu LongInt, Short zu
  2684. Integer, Exit zu Halt, usw. Vielleicht wird sogar Unit-Syntax eingebaut.
  2685.  
  2686. Das andere Gebiet, das der Autor gerne erforschen würde, wären Debugger,
  2687. vor allem Sourcelevel-Debugger.
  2688.  
  2689.  
  2690.  
  2691. 23. Update-History
  2692. ^^^^^^^^^^^^^^^^^^
  2693.  
  2694. (Sorry, aber ich hatte wirklich keinen Bock, die gesamte Update-History zu
  2695.  übersetzen. Daher müßt ihr eben in der englischen Anleitung nachsehen! -
  2696.  Anm.d.Ü.)
  2697.  
  2698.  
  2699.  
  2700. 24. Weitere Anmerkungen, Copyright und Adressen
  2701. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  2702.  
  2703. Wie bereits erwähnt, liegt das Copyright für die Anleitung, für den Compiler
  2704. selbst, den Sourcecode und der Run-Time-Library bei:
  2705.  
  2706.     Copyright © 1989 Patrick Quaid
  2707.  
  2708. Es ist erlaubt, das Paket frei zu vertreiben, solange alle Dateien (mit
  2709. Ausnahme des Linkers und des Assemblers; trotzdem bitte mitkopieren, falls
  2710. möglich) unverändert beigefügt sind. Niemand darf mit diesem Programm Geld
  2711. verdienen! Es darf nur auf Disk-Sammlungen weitergegeben werden, für die ein
  2712. vernünftiger Preis genommen wird (Maximum ist DM 5,- in Deutschland).
  2713.  
  2714. Sie können den Compiler jederzeit für Ihre eigenen Zwecke verändern, wenn
  2715. Sie wollen. Ich wäre Ihnen jedoch dankbar, wenn Sie mir dann, falls Sie
  2716. diese Version besser finden als das Original, eine Kopie zuschicken würden,
  2717. damit ich dies dann in die nächste Version mit einbinden kann. Besonders in-
  2718. teressiert ist der Autor im Bezug auf Verbesserungen in der Richtung von in-
  2719. tegrierten Umgebungen mittels ARexx oder so. Sollten Sie jedoch grundlegende
  2720. Dinge am Compiler verändern, die nicht mehr dem Standard von Pascal oder der
  2721. obigen Beschreibung entsprechen, dann geben Sie eine Kopie dieses modifizier-
  2722. ten Compilers bitte NICHT unter dem Namen PCQ weiter, da sonst nur Mißver-
  2723. ständnisse aufkommen.
  2724.  
  2725. Dies ist kein ShareWare-Produkt, d.h. Sie müssen kein schlechtes Gewissen
  2726. haben, falls nichts bezahlen, wenn Sie es verwenden. Wenn Sie mir wirklich
  2727. helfen wollen, dann schreiben Sie mir über Ihre Erfahrungen und vor allem
  2728. über die Fehler, die Sie entdeckt haben. Schreibt nicht über unimplementier-
  2729. ten Features - der Autor weiß über sie bescheid! Er versucht nicht den für
  2730. alle Zeiten besten Pascal-Compiler zu schreiben, aber er soll korrekt sein!
  2731. Sollten Ihr ein Bedürfnis verspüren, unbedingt Geld loswerden zu wollen, dann
  2732. schickt es an Charlie Gibbs, der den Assembler geschrieben hat oder an die
  2733. Software Distillery, die den Linker geschrieben haben.
  2734.  
  2735. Falls Ihr die aktuelle Version vom Autor haben wollt, schickt dem Autor 2,25$
  2736. (.50$ Umschlag, .75$ Porto, Disks 1$) bzw. nach Europa 3,00$ (das Porto ko-
  2737. stet hier um die 1,50$). Ein etwas höherer Betrag wäre für die Kostendeckung
  2738. des Autors recht nützlich.
  2739.  
  2740. Solltet Ihr irgendwelche Fragen, Kommentare oder was auch immer haben, dann
  2741. schreibet (in Englisch!) an:
  2742.  
  2743.           Pat Quaid
  2744.           8320 E.Redwing
  2745.           Scottsdale, AZ 85250
  2746.           USA
  2747.  
  2748.           Tel.: (602) 967-3356
  2749.           FidoNetz: Patrick Quaid @ 1:114/52
  2750.  
  2751. Ihr könnt den Autor eher per Post als per Telefon erreichen.
  2752.  
  2753. Haben Sie Spaß mit dem Compiler! Falls Sie Beschwerden haben, denken Sie an
  2754. den Preis! (Falls Sie etwas bezahlt haben, wenden Sie Sich an den, der das
  2755. Geld gekriegt hat!)
  2756.  
  2757.  
  2758.  
  2759. 25. Stichwortverzeichnis
  2760. ^^^^^^^^^^^^^^^^^^^^^^^^
  2761.  
  2762. Nachfolgend habe ich versucht, eine Übersicht über die im Anleitungstext be-
  2763. schriebenen Funktionen (mit Zeilenangabe) zu erstellen. Natürlich ist diese
  2764. Liste wahrscheinlich nicht vollständig, sie müßte aber alles wichtige enthal-
  2765. ten. Außerdem stimmen die Zeilennummern manchmal nicht ganz (+/- 5 Zeilen) -
  2766. Dieser Teil ist NICHT in der engl. Anleitung enthalten gewesen, sondern kom-
  2767. plett neu von mir erstellt worden. Der Übersetzer.
  2768.  
  2769.  
  2770. 25.1 Allgemeine Begriffe
  2771. ------------------------
  2772.  
  2773. Abs() ......... 898
  2774. Address ....... 534
  2775. Adr() ......... 894
  2776. AllocString() . 2065
  2777. ArcTan() ...... 902
  2778. Array ......... 556,1792,1843,2085
  2779. Assignment .... 1512
  2780. Bit() ......... 905
  2781. Boolean ....... 529,1798,1857
  2782. Byte .......... 516,1780,1828
  2783. Case .......... 1041,1430
  2784. Char .......... 527,1790,1841
  2785. Ceil() ........ 912
  2786. Chr() ......... 908,2111
  2787. Close() ....... 756
  2788. CommandLine ... 597
  2789. Const ......... 411,1247
  2790. Cos() ......... 915
  2791. Dec() ......... 761
  2792. Dispose() ..... 774
  2793. Enumerated .... 544
  2794. Eof() ......... 918
  2795. Exit .......... 779
  2796. ExitAddr ...... 617,2249
  2797. ExitCode ...... 611,2244
  2798. ExitProc ...... 605,2214
  2799. Exp() ......... 922
  2800. False ......... 472
  2801. Float() ....... 925
  2802. Floor() ....... 931
  2803. For ........... 1051,1388
  2804. Function ...... 881,1062
  2805. Get() ......... 796, 1906
  2806. Goto .......... 1569
  2807. HeapErr ....... 622
  2808. HeapFunc ...... 2207
  2809. If ............ 1317
  2810. Inc() ......... 802
  2811. Input ......... 628
  2812. Integer ....... 510,1778,1826
  2813. IOResult ...... 934,1677,1934
  2814. Ln() .......... 943
  2815. MaxInt ........ 474,1042
  2816. MaxShort ...... 478
  2817. New() ......... 812
  2818. Nil ........... 483
  2819. Odd() ......... 947
  2820. Open() ........ 950,1740
  2821. Ord() ......... 959, 2453
  2822. Output ........ 635
  2823. Pred() ........ 964
  2824. Procedure ..... 399,649,743,1062,1524,2552
  2825. Program ....... 326,393,2517
  2826. Put() ......... 817,1920
  2827. Read() ........ 823,1815
  2828. ReadLn() ...... 829, 1873
  2829. Real .......... 525,1784,1836
  2830. Record ........ 262,1617
  2831. ReOpen() ...... 970,1709
  2832. Repeat ........ 1368
  2833. Reset() ....... 838,1685
  2834. Return ........ 1062,1551
  2835. Rewrite() ..... 849,1725
  2836. Round() ....... 978
  2837. Short ......... 512,1779,1827
  2838. Sin() ......... 983
  2839. SizeOf() ...... 987
  2840. Sqr() ......... 991
  2841. Sqrt() ........ 994
  2842. StdInName ..... 2000
  2843. StdOutName .... 2001
  2844. Strcpy() ...... 2077
  2845. Strdup() ...... 2072
  2846. String ........ 531,1795,1850
  2847. Succ() ........ 997
  2848. Tan() ......... 1002
  2849. Text .......... 538
  2850. Trap() ........ 859
  2851. True .......... 488
  2852. Trunc() ....... 1008,2457
  2853. Type .......... 261,395,441,505
  2854. Var ........... 393,570,1256
  2855. While ......... 1346
  2856. With .......... 1466
  2857. Write() ....... 865,1762
  2858. WriteLn() ..... 872,1801
  2859.  
  2860.  
  2861. 25.2 Mathematische Operatoren
  2862. -----------------------------
  2863.  
  2864. @   1166
  2865. -   1168,1197
  2866. +   1169,1196
  2867. *   1177
  2868. /   1178
  2869. =   1206
  2870. <>  1207
  2871. >   1208
  2872. <   1210
  2873. >=  1212
  2874. <=  1214
  2875. and 1184
  2876. div 1180
  2877. mod 1182
  2878. not 1170
  2879. or  1198
  2880. shl 1185
  2881. shr 1187
  2882. xor 1199
  2883.  
  2884.  
  2885. 25.3 Compiler-Direktiven
  2886. ------------------------
  2887.  
  2888. {$A}        2340
  2889. {$B+|-}     2346
  2890. {$I""}      2365
  2891. {$I+|-}     1943,2370
  2892. {$O+|-}     2418
  2893. {$R+|-}     2423
  2894. {$SN|X|P|D} 2390
  2895.  
  2896.  
  2897.  
  2898. 26. ABSCHLIESSENDE KURZINFORMATIONEN
  2899. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  2900.  
  2901. So, das wär´s nun endlich. Ich hoffe, Ihr blickt jetzt einigermaßen durch...
  2902. Wie bereits erwähnt, ist die engl. Anleitung nicht vollständig übersetzt (so
  2903. etwa zu 90 % müßte sie aber übersetzt sein). Außerdem wurde einiges zum bes-
  2904. seren Verständnis angefügt. Das Stichwortverzeichnis ist sowieso komplett von
  2905. mir erstellt worden. Die engl. Anleitung war außerdem nicht kapitelmäßig
  2906. durchnumeriert. Das habe ich angefügt, damit Ihr Euch besser zurechtfindet.
  2907. Bemerkungen zur dt. Übersetzung bitte an Stefan Grad, Bahnhofstr. 37, 78588
  2908. Denkingen, Deutschland. Die Adresse des Programmautors befindet sich im Kapi-
  2909. tel 24.
  2910.  
  2911. Alle Angaben in dieser Anleitung ohne Gewähr! Wenn Ihr damit irgendwas zer-
  2912. stört, können weder der Programmautor noch der Autor der deutschen Anleitung
  2913. dafür haftbar gemacht werden!
  2914.  
  2915. Programm-Name:      PCQ-Pascal V1.2b
  2916. Programm-Autor:     Patrick Quaid
  2917. Herkunft:           Purity 3 und 6; Fish 503, 504 und 511
  2918. Dt. Anleitung:      Stefan Grad (GPD) für Purity
  2919.  
  2920.